spring-io / initializr

A quickstart generator for Spring projects
https://start.spring.io
Apache License 2.0
3.45k stars 1.74k forks source link

Merge cloud-start.spring.io and start.spring.io #93

Closed rwinch closed 9 years ago

rwinch commented 9 years ago

Speaking with @dsyer cloud-start.spring.io was initially done to provide a good test bed for allowing extending start.spring.io. This was so that developers could do this for their own auto configurations within their company.

Now that this has been proven out it makes sense to merge cloud-start.spring.io into start.spring.io so that our user's experience is not fragmented (i.e. we don't want a start-start.spring.io to list all the available endpoints).

snicoll commented 9 years ago

okay, @dsyer your instance is driven by the spring cloud version. How do you think we should deal with that?

bclozel commented 9 years ago

Revisiting the current UI is probably necessary - merging both would create too many choices in a single form...

snicoll commented 9 years ago

Well, I don't want to loose the experience of changing a few fields, press enter and have a project archive as an output. But I get what you mean.

I gave it a lot of thought and the core of this issue sounds about choosing a framework to me. So here is what I propose.

First, let's create a new capability called frameworks with the usual core capability properties, that is name, id, description and default. We'll have two kind of frameworks in our instance: boot and cloud (I guess springBoot and springCloud are probably better ids, more on that later).

We can then reuse a discussion we already had concerning bootVersion that should be renamed to frameworkVersion. If we combine those two (that is the type of framework and the chosen version) we can update the ProjectGenerator to tune the way the project is generated, including different template for certain things if that's necessary. The cool thing about it is that the type of framework is part of the ProjectRequest now so we can basically do what we want.

As far as backward compatibility is concerned, ProjectRequest#resolve can be open a bit so that if bootVersion is specified, the frameworkVersion takes that value and the framework attribute switch to boot automagically. We can do the same with cloudVersion and extract that in a determineFramework(InitializrMetadata metadata) method that one could override. Because we already have bootVersion, it's probably better to name our framework id for Spring Boot boot.

On the UI side now, I am definitely not an expert but something that I would see is putting the framework right in the face of the user so instead of having a select at the bottom left of the form, have a select in the top center where user can choose either "Spring Boot" or "Spring Cloud" and when they select one, a version select field is enabled to tune the version.

Finally, we need to tune the dependencies that we show based on the framework. That is pretty much similar to our version range story. There are multiple ways we can do this but I guess we could have a supportedFrameworks list on each Dependency that the UI would read to figure out what to show. Configuration-wise we could have a structure where the dependencies are split between frameworks and we could choose to extend one from another. Something like

initializr:
  dependencies:
    cloud:
      extends: boot
      groups:
        - name: Cloud
          content:
            - name: Config Server
              id: cloud-server
              description: Support for spring-cloud-config Server
              groupId: ${cloud.groupId}
              artifactId: spring-cloud-config-server
         ...
    boot:
      groups:
        - name: Core
          content:
            - name: Security
              id: security
              description: Support for spring-security

the boot groups would have boot and cloud as supported frameworks. Of course the meta-data customizer still allows to reorder the groups or even add/remove supported frameworks for certain dependencies if that's necessary.

InitializrMetadata would therefore index dependency by framework as well, offering dedicate methods to retrieve all dependencies or a dependency by id that match a given framework id.

How does that sound? This might deserve a proper v3 and wouldn't break anything actually as existing client would specify bootVersion and everything would work as before.

dsyer commented 9 years ago

I have the feeling that allowing the user to choose the "framework" might be too much (confusing and possibly unnecessary). I have an alternative proposal.

A dependency group can optionally specify a BOM and/or preferred parent. When a depdendency from that group is chosen, then a BOM is added to the <dependencyManagement/> (and equivalent using the gradle plugin). If the group says that it has a preferred parent then we can use it (after applying a conflict resolution algorithm, e.g. priority ordered).

Taking the Spring Cloud use case as an example, it should work out fine because of the dependency version range support we already have (Spring Cloud only makes sense with Spring Boot 1.2.2).

snicoll commented 9 years ago

And how do you select the Spring cloud vs. the Spring boot version exactly?

dsyer commented 9 years ago

You only need to select the boot version (just like the existing service). The cloud version is part of the metadata for the dependencies.

snicoll commented 9 years ago

okay so we have bom support in #99 so I guess we need to tune a few things:

  1. A group may define a bom (each dependency in the group is associated to that bom)
  2. What do we do if we want to promote a milestone of the cloud dep? Or two cloud versions? You actually need a mapping between the boot version and the cloud version. How are you going to do that?
snicoll commented 9 years ago

Here is a first attempt to merge the two instances in a single one

http://start-development.cfapps.io/

There is one small glitch: Cloud connectors should probably move from the Ops group to the Cloud group. Can you guys can try it out and let me know if that works out for you? I am using spring-cloud-versions as the BOM when a cloud dependency is selected.