Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize the way the spring-initializr works?

As an enterprise we would like to host the initializr internally on our PCF instance, which I can do. I've also been able to modify application.yml to default some of the selections.

I did this by simply creating my own spring-boot app which uses io.spring.initializr:initializr-web:0.3.0.RELEASE as a runtime dependency.

I have 2 main questions:

  1. Is there a way on the UI to default selections of certain dependencies when the UI first comes up (i.e. pre-selecting Web & Security for instance)?
  2. Can I customize the output of the generation? For instance we have our own custom distro of Gradle and would like the generated build.gradle file to look a bit different than what the initializr generates. We'd also like to generate a gradle.properties file as part of the project.
like image 457
Eric Avatar asked Apr 14 '17 20:04

Eric


People also ask

How does Spring Initializr work?

The Spring Initializr is ultimately a web application that can generate a Spring Boot project structure for you. It doesn't generate any application code, but it will give you a basic project structure and either a Maven or a Gradle build specification to build your code with.

Which of the following are options supported by spring Initializr?

Spring Initializr is supported by various IDEs like Spring Tool Suite(STS), IntelliJ IDEA Ultimate and IntelliJ IDEA Community Edition(Limited Configuration options), Netbeans, and VSCode.

How do I run spring Initializr locally?

The easiest way to run the server is to have the Spring CLI tool installed. The easiest way to install it is using SDKMAN!. We type $ sdk install springboot on the command line. Next we create a new directory and inside the directory we create a new Groovy file initializr.


2 Answers

There is a reference guide that walk you through the creation of your own instance. Regarding your main questions:

Yes this is possible in a custom instance. Implement ProjectRequestPostProcessor and add those two dependencies to the project.

@Component
class PreselectedDependenciesRequestPostProcessor implements ProjectRequestPostProcessor {

    private final InitializrMetadataProvider metadataProvider;

    public PreselectedDependenciesRequestPostProcessor(
            InitializrMetadataProvider metadataProvider) {
        this.metadataProvider = metadataProvider;
    }

    @Override
    public void postProcessAfterResolution(ProjectRequest request,
            InitializrMetadata metadata) {
        DependenciesCapability dependencies = metadataProvider.get().getDependencies();
        if (!hasDependencies(request, "web")) {
            request.getResolvedDependencies().add(dependencies.get("web"));
        }
        if (!hasDependencies(request, "security")) {
            request.getResolvedDependencies().add(dependencies.get("security"));
        }
    }

    private boolean hasDependencies(ProjectRequest request, String... dependenciesId) {
        for (String id : dependenciesId) {
            if (getDependency(request, id) == null) {
                return false;
            }
        }
        return true;
    }

    private Dependency getDependency(ProjectRequest request, String id) {
        return request.getResolvedDependencies().stream()
                .filter(d -> id.equals(d.getId())).findFirst().orElse(null);
    }
}

They won't be selected in the UI but they'll be integrated in the project the same way as if the user had selected them. The reason why I recommend this approach is that your custom instance can be targeted by the IDE integration the same way as the main (start.spring.io) instance. Hacking the web UI will only make this work with that particular client which, IMO, is a problem.

For the second question, most forks extend from ProjectGenerator and do whatever they want (including overriding the gradle build). Check that class for more details.

Spring Initializr hasn't reached 1.0 yet so it's not in a state where the contract is mature enough.

like image 128
Stephane Nicoll Avatar answered Sep 30 '22 12:09

Stephane Nicoll


I have done a bunch of this for our internal usage and will be presenting this at a talk tomorrow at gr8conf.

Putting in custom files and adding default selections is pretty easy and requires a bit of knowledge of modifying the java, css and html. You can get the source for the work I have done to demo this here: https://github.com/Grails-Plugin-Consortium/initializr/tree/master

The code requried to change is lengthy so the easiest way to get a sense of the work I had to do to accomplish this is to just link the diff from adding the "Default" selections and app profiles.

https://github.com/Grails-Plugin-Consortium/initializr/commit/feae678fdd4503c2314635cebdaabc04b4d80ace

Adding custom files to get added to generated apps is a bit easier and only requires that you add the files to the templates in initializr-generator and then add a link in ProjectGenerator.java to copy the file similar to how the existing code is already implemented.

protected void generateDockerFile(File dir, Map<String, Object> model){
    write(new File(dir, "Dockerfile"), "Dockerfile", model);
    write(new File(dir, "docker.sh"), "docker.sh", model);
    write(new File(dir, "docker-run.sh"), "docker-run.sh", model);
}

The method above added to the ProjectGenerator will add the following files stored in initializr/initializr-generator/src/main/resources/templates/

All of the heavy lifting for generation lives in this file: https://github.com/Grails-Plugin-Consortium/initializr/blob/9b302d31bb069c9c702f36ed765ad3f55debff84/initializr-generator/src/main/java/io/spring/initializr/generator/ProjectGenerator.java

like image 36
Christian Avatar answered Sep 30 '22 12:09

Christian