Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Spring-Boot integration #134

Closed
php-coder opened this issue May 19, 2015 · 56 comments
Closed

Add Spring-Boot integration #134

php-coder opened this issue May 19, 2015 · 56 comments

Comments

@php-coder
Copy link

I'd like to have out-of-box integration with Spring Boot.

@chkal
Copy link
Member

chkal commented May 22, 2015

Could you tell us what you are missing. Basically I assumed that using the togglz-spring module should be all you need to get Togglz up and running in Spring Boot applications.

@php-coder
Copy link
Author

tooglz-spring is only enough for "old" Spring applications. When we are using Spring Boot there is a additional ways to reduce configuration even more and make it work out of box (with minimal or zero configuration).

Minimal rules that will make my application work mostly ouf-of-box are:

  1. TogglzConsoleServlet should be created as ServletRegistrationBean when:
    • togglz-console present in classpath
    • property togglz.console.enabled has value true
      • property togglz.console.enabled is absent and this is a web application

1a) TogglzConsoleServlet should has mapping from property togglz.console.mapping (that has default value /togglz/*)

  1. InMemoryStateRepository should be created if there is no beans of type StateRepository

3a) May be we should create JDBCStateRepository if there is a bean of type DataSource (?) (in this case we should run after DataSourceAutoConfiguration)

  1. SpringSecurityUserProvider should be created if togglz-spring-security present in classpath and property togglz.security.enabled is absent or has value true and there is no bean of type UserProvider

4a) SpringSecurityUserProvider should be initialized with value of property togglz.security.authority (that has default value ADMIN)

  1. Default ActivationStrategy should be created if there is no bean of type ActivationStrategy

  2. FeatureManager should be created if there are beans of the following types in context:

    • StateRepository
    • UserProvider
    • ActivationStrategy
    • Feature
      and property togglz.enabled is absent or has value true and there is no bean of type FeatureManager
  3. StaticFeatureManagerProvider should be initialized with FeatureManager created on the previous step (we may try to use ApplicationContextInitializer to accomplish that)

When all these will be packed into, let's say, togglz-spring-boot, I need to do the following steps:

  • add togglz-spring-boot to dependencies
  • add bean of type Feature
  • add togglz-spring-security to dependencies or create bean of type UserProvider
    and that's all!

@chkal
Copy link
Member

chkal commented May 26, 2015

Interesting approach. I have a few question though:

  • So you have to create a ServletRegistrationBean to automatically register a servlet with Spring Boot? So isn't web-fragment.xml registration not supported at all?
  • I think all this Spring Boot specific initialization code could be handled by a SpringBootFeatureManagerProvider. So the initialization would be performed lazily as soon as Togglz is first used. Do you think this could work? Or has such initialization work to be one during the Spring Boot initialization procedure?

@csavory
Copy link

csavory commented Jun 18, 2015

@chkal usually there is no web.xml or web-fragment.xml in a Spring Boot application. Most of them will use an Embedded Tomcat (by default) or Jetty if Jetty is on the classpath.

@devluencer-089
Copy link

+1

@chkal
Copy link
Member

chkal commented Oct 8, 2015

Any contributions for improved Spring Boot support are more than welcome. I'm not very familiar with Spring Boot so any help there would be great.

@mariuszs
Copy link

mariuszs commented Dec 9, 2015

👍

@binkley
Copy link

binkley commented Jan 10, 2016

I have two bits of sample code I'm working on:

  1. Wire vs ignore beans annotated with @ConditionalOnFeature(... enum value ...) - only create bean if toggle is enabled
  2. Same for individual request handler methods of a Spring controller (see http://binkley.blogspot.com/2016/01/spring-techniques-feature-toggles-for.html for approach but not details)

Would either of these be helpful? I'm happy to contribute the code, and it's all public domain.

@marceloverdijk
Copy link

I'm quite interested in this myself and have written custom Boot starters/autocofigurations already; I will have a look at this.

@marceloverdijk
Copy link

@chkal would you be interested in a contributed togglz-boot module which acts as a starter and autoconfiguration for Spring boot.
Meaning it will autoconfigure Togglz automatically with sensible defaults but off course this can be changed/overridden by the users.

@chkal
Copy link
Member

chkal commented Jan 11, 2016

@marceloverdijk & @binkley:

Of cause I'm interested in any kind of contribution for Spring Boot integration. Especially as I'm not very familiar with Spring Boot. I see there are many people looking forward to improved support for Spring Boot.

If you need any help or if you would like to discuss the technical details before starting to code feel free to post on this thread. :)

@marceloverdijk
Copy link

@chkal I'm setting up a sample project this week and are also discussing this with the Boot guys.
From there we can see where we can put the code best: Spring Boot, Togglz, or a standalone project. I will keep you informed.

@php-coder
Copy link
Author

@marceloverdijk IMHO it's better to name module togglz-spring-boot instead of togglz-boot. Also I could test it when it will be ready.

@chkal
Copy link
Member

chkal commented Jan 11, 2016

@marceloverdijk Awesome. Thanks a lot.

@php-coder +1 for togglz-spring-boot if the code is contributed to Togglz instead of adding it to Spring boot directly... And thanks for your help with testing.. :)

BTW: I just wrote a few lines about how to contribute to Togglz:

https://github.com/togglz/togglz/wiki/Contributing

@marceloverdijk
Copy link

Yes indeed togglz-spring-boot is a better name.

@marceloverdijk
Copy link

I have a - in progress - sample at https://github.com/marceloverdijk/spring-boot-togglz
It uses Spring Boot to configure Togglz automatically.

@php-coder
Copy link
Author

As I can see you've create the project that is the sample how to use Spring Boot with Togglz. Could you create a separate project just with this integration piece? In this case I could add it as the Maven dependency to my project. Also, why you're using com.mycompany package? It looks a bit weird and unexpected.

@marceloverdijk
Copy link

@php-coder Yes this is the idea! Currently it's work in progress.
When it's finished I need to check if we can add this to Boot or as separate module in togglz project.
Won't take to long I think.

@marceloverdijk
Copy link

@php-coder new location: https://github.com/marceloverdijk/togglz-spring-boot and the starter is now included in separate module. Still work in progress!

@marceloverdijk
Copy link

@php-coder https://github.com/marceloverdijk/togglz-spring-boot is getting in good shape.
It contains some samples as well.
Please feel free to provide feedback.

@php-coder
Copy link
Author

@marceloverdijk How I can use it as Maven dependency?

@marceloverdijk
Copy link

Hi Vyacheslav,

Currently we don't have this in Maven as it's work in progress.
But you can already build it locally using gradlew clean install
In that the starter is deployed to you local maven repo and you can add in
to your project.

Let me know if you need additional help.

Hopefully in not to long time I will publish something to Maven central.

On Tue, Jan 19, 2016 at 3:39 PM, Vyacheslav Semushin <
notifications@github.com> wrote:

@marceloverdijk https://github.com/marceloverdijk How I can use it as
Maven dependency?


Reply to this email directly or view it on GitHub
#134 (comment).

@marceloverdijk
Copy link

@php-coder I haven't managed to deploy a snapshot to maven. However you can build it easily locally for now. See "Building from Source" section at https://github.com/marceloverdijk/togglz-spring-boot.
It's basically just running gradlew clean install and you add the dep as Maven dep to your project. As it uses the Gradle wrapper you don't even have to install Gradle.

@php-coder
Copy link
Author

@marceloverdijk Ok, thanks! I will try to use https://jitpack.io/ for building the artifacts for Maven.

Could you also add auto configuration for Thymeleaf Togglz Dialect? (https://github.com/heneke/thymeleaf-extras-togglz).

Also I want to ask: before I used JDBCStateRepository with CachingStateRepository. Does your integration support such scenario?

@php-coder
Copy link
Author

It fails with error: java.lang.NoClassDefFoundError: org/togglz/spring/util/ContextClassLoaderApplicationContextHolder Looks like, I need some dependency..

@chkal
Copy link
Member

chkal commented Jan 20, 2016

You have to update Togglz to 2.3.0-SNAPSHOT to use the Spring Boot integration.

See this page for details on how to use the snapshots:

http://www.togglz.org/download.html

@marceloverdijk
Copy link

@php-coder You can define your own StateRepository bean. In that case the auto configuration will not create one. The FeatureManager created by the auto configuration will use it automatically.

@php-coder
Copy link
Author

I would like to remove my Togglz config completely. To do so I need to have ability to

  1. define FeatureProvider in application.{yml,properties} (maybe you could add togglz.feature-class-name property?)
  2. use CachingStateRepository (maybe you could add togglz.repository.cache-enabled property)
  3. auto-register of Thymeleaf Togglz Dialect

@marceloverdijk
Copy link

@php-coder

  1. Yes I had a property like this but removed it. Will add it again.
  2. Yes good point. I will add this.
  3. I will look into this.

@marceloverdijk
Copy link

@php-coder Both 1) and 2) are now implemented. See the README at the https://github.com/marceloverdijk/togglz-spring-boot with new configuration properties.
Also both /samples have been updated to demonstrate usage of feature-enum property (hello-world sample) and the cache capability (spring-security) sample.

Hope to have a look at 3) tomorrow.

@binkley
Copy link

binkley commented Jan 20, 2016

I've been noodling at this for a while. The main impediments at present:

  1. Injecting the FeatureManager into the Spring conditional @ConditionalOnFeature(...)
  2. Getting boot auto-configuration "just right", though I'm pretty close on this

I'm providing application settings like this:

features:
  togglz:
    annotation-type: hm.binkley.eg.features.ConditionalOnFeature
    enum-type: hm.binkley.eg.features.EgFeature

@binkley
Copy link

binkley commented Jan 20, 2016

I also have some extra working code to use a feature toggle annotation on controller endpoint hander methods, rather than on the entire controller class.

@marceloverdijk
Copy link

@binkley please have a look at https://github.com/marceloverdijk/togglz-spring-boot it contains quite comprehensive support for Togglz autoconfiguration.

Can you share some more details regarding you @ConditionalOnFeature and how to use feature toggle on controller endpoints. The latter one sound more like a Toggle Spring-Web functionality (with auto configuration in the Togglz Spring Boot module).

@marceloverdijk
Copy link

@binkley is you code public available?

@binkley
Copy link

binkley commented Jan 21, 2016

@marceloverdijk Right. It's licensed as Public Domain, but I haven't put it up in GitHub yet as I wanted to work out the issues I mentioned. Apologies. Let me see what I can do & post back when ready.

A "not ready" but working scratch version is there. It's missing some of the key goals I want, but does demonstrate the approach we took for putting toggle annotations on controller endpoint methods:

https://github.com/binkley/springy-boxy/tree/develop/src/main/java/hm/binkley/boxfuse

Was also trying to reproduce in the small some of the issues we encountered in a large, non-public project in which we're using this approach. Essentially we're hooking into Spring MVC to ignore @RequestMapping methods in a controller whose toggle is disabled.

Frankly, this is not a good area for Spring Framework.

@binkley
Copy link

binkley commented Jan 21, 2016

@marceloverdijk The approach above is working through Spring MVC. We're also spiking an approach with Spring AOP. It would not be quite as flexible, but more promising for lower impact on our internal project. Spring MVC & Boot have so many different extension points, our own codebase has tripped over itself with inconsistency among different teams.

@marceloverdijk
Copy link

@binkley Are we having overlap with the Spring Boot integration? I also put a lot of effort in it and it is getting quite stable now.

@binkley
Copy link

binkley commented Jan 21, 2016

@marceloverdijk I'll definitely be looking yours over today. I hate to write code when I can reuse. :-) Also, happy to contribute if I have something not covered in your project. Thanks!

@marceloverdijk
Copy link

@php-coder I just added the Thymeleaf Togglz dialect.
Please pull the git repo and install a new snapshot.
When you add the thymeleaf-extras-togglz dep to your project the auto configuration will add the dialect automatically. I've even create a Thymeleaf sample at https://github.com/marceloverdijk/togglz-spring-boot/tree/master/samples/togglz-spring-boot-sample-thymeleaf.

@marceloverdijk
Copy link

BTW: just pushed a commit that changes the default Togglz admin console path to /togglz-console (was just /togglz). This to create Boot endpoint on /togglz to just display current feature sates.

@marceloverdijk
Copy link

Added a Togglz actuator endpoint for viewing feature states over jmx/http to masterat https://github.com/marceloverdijk/togglz-spring-boot

@php-coder
Copy link
Author

@marceloverdijk Thank you for the great work! It addresses most of my requirements, except one:

3a) May be we should create JDBCStateRepository if there is a bean of type DataSource (?) (in this case we should run after DataSourceAutoConfiguration)

Is it possible that you will solve it?

@marceloverdijk
Copy link

@php-coder I think almost every application has a DataSource but not all of them would use a JDBCStateRepository. E.g. personally I would use a file in most cases.
You can always provide your own StateRepository like:

@Bean
public StateRepository stateRepository() {
    return new JDBCStateRepository(dataSource);
}

@marceloverdijk
Copy link

@chkal the Boot team tends to prefer to add the Togglz - Boot integration to a Togglz module.
Shall I work on a PR to include it as a submodule to the project.
I favor to name it togglz-spring-boot-starter as it is basically a starter containing auto configuration.
Best would be to separate the autoconfigure code to a second togglz-spring-boot-autoconfigure module.
Is that ok for you if I create 2 submodules?

@chkal
Copy link
Member

chkal commented Feb 9, 2016

Sure, as I wrote before I would be happy to see the Spring Boot support as a Togglz module. So go ahead and prepare a pull request.

Creating two modules is fine if it makes sense for the users. But I'm not sure if I understood the distinction between the two correctly. Could you explain this a bit more?

@marceloverdijk
Copy link

OK I will work on a PR.
For the distinction see http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-custom-starter
Basically the *-autoconfigure module is never used directly by the user, so re-thinking about it, I doubt if there is a benefit of using 2 modules.
Following the Boot naming conventions we should then create a module togglz-spring-boot-starter.
Hopefully I will push something today or tomorrow!

@marceloverdijk
Copy link

PR #154 created.

@chkal
Copy link
Member

chkal commented Feb 9, 2016

Ok, thanks for explaining. I also think that one module should be enough. I don't see a real benefit of splitting it into. I'm just wondering if we should name module togglz-spring-boot instead. If we don't split into starter and autoconfigure, this may be simpler? And it would follow the naming conventions for the other Togglz modules...

@marceloverdijk
Copy link

-starter suffix is a good naming convention for Spring Boot Starters as it states explicitly what it is.
I think for now that's the best name. If you really want to name it differently, that's ok for me :-)

@chkal
Copy link
Member

chkal commented Feb 9, 2016

No, I'm fine with this suffix. If it is a common Spring Boot naming convention, we should keep it.

Thanks a lot for the PR. Unfortunately I'm currently very busy. But I hope I'll find some time to have a depper look at it tomorrow...

@marceloverdijk
Copy link

OK no problem. I need to write the documentation anyway.

@marceloverdijk
Copy link

And here is the PR for the documentation: togglz/togglz-site#4

chkal added a commit that referenced this issue Feb 12, 2016
@binkley
Copy link

binkley commented Feb 19, 2016

Any timeline on release of 2.3.0? I'd like to get this feature into the hands of my teams. :-)

@chkal
Copy link
Member

chkal commented Feb 19, 2016

I would love to get some more feedback if possible. Perhaps we could release 2.3.0.RC1 soon. As soon as the bits are in Maven Central, more people will probably try it. :)

@chkal
Copy link
Member

chkal commented Feb 23, 2016

FYI: Togglz 2.3.0.RC1 has been released. This version ships with the new Spring Boot support by @marceloverdijk. Any kind of feedback is welcome. :)

@marceloverdijk
Copy link

I think we can close this issue now. Boot support is now available since 2.3.0.RC1 and additional requests can be requested/captured via new issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants