Move generator templates to Mustache

This commit is contained in:
Dave Syer 2017-02-09 12:13:43 +00:00 committed by Stephane Nicoll
parent ac20d04985
commit fffcd8a774
32 changed files with 501 additions and 307 deletions

View File

@ -20,20 +20,14 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-templates</artifactId>
<groupId>com.samskivert</groupId>
<artifactId>jmustache</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@ -26,7 +26,7 @@ import org.springframework.beans.BeanWrapperImpl;
import io.spring.initializr.metadata.Dependency;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.Type;
import io.spring.initializr.util.GroovyTemplate;
import io.spring.initializr.util.TemplateRenderer;
/**
* Generate help pages for command-line clients.
@ -42,9 +42,9 @@ public class CommandLineHelpGenerator {
+ " ' |____| .__|_| |_|_| |_\\__, | / / / /\n"
+ " =========|_|==============|___/=/_/_/_/";
private final GroovyTemplate template;
private final TemplateRenderer template;
public CommandLineHelpGenerator(GroovyTemplate template) {
public CommandLineHelpGenerator(TemplateRenderer template) {
this.template = template;
}

View File

@ -43,7 +43,7 @@ import io.spring.initializr.metadata.Dependency;
import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.util.GroovyTemplate;
import io.spring.initializr.util.TemplateRenderer;
import io.spring.initializr.util.Version;
/**
@ -79,7 +79,7 @@ public class ProjectGenerator {
private ProjectRequestResolver requestResolver;
@Autowired
private GroovyTemplate groovyTemplate = new GroovyTemplate();
private TemplateRenderer templateRenderer = new TemplateRenderer();
@Autowired
private ProjectResourceLocator projectResourceLocator = new ProjectResourceLocator();
@ -106,8 +106,8 @@ public class ProjectGenerator {
this.requestResolver = requestResolver;
}
public void setGroovyTemplate(GroovyTemplate groovyTemplate) {
this.groovyTemplate = groovyTemplate;
public void setTemplateRenderer(TemplateRenderer templateRenderer) {
this.templateRenderer = templateRenderer;
}
public void setProjectResourceLocator(ProjectResourceLocator projectResourceLocator) {
@ -299,7 +299,13 @@ public class ProjectGenerator {
*/
protected void generateGitIgnore(File dir, ProjectRequest request) {
Map<String, Object> model = new LinkedHashMap<>();
model.put("build", isGradleBuild(request) ? "gradle" : "maven");
if (isMavenBuild(request)) {
model.put("build", "maven");
model.put("mavenBuild", true);
}
else {
model.put("build", "gradle");
}
write(new File(dir, ".gitignore"), "gitignore.tmpl", model);
}
@ -323,7 +329,12 @@ public class ProjectGenerator {
log.info("Processing request{type=" + request.getType() + ", dependencies="
+ dependencyIds);
if (isWar(request)) {
model.put("war", true);
}
if (isMavenBuild(request)) {
model.put("mavenBuild", true);
ParentPom parentPom = metadata.getConfiguration().getEnv().getMaven()
.resolveParentPom(request.getBootVersion());
if (parentPom.isIncludeSpringBootBom()
@ -338,10 +349,18 @@ public class ProjectGenerator {
model.put("includeSpringBootBom", parentPom.isIncludeSpringBootBom());
}
model.put("repositoryValues", request.getRepositories().entrySet());
if (!request.getRepositories().isEmpty()) {
model.put("hasRepositories", true);
}
model.put("resolvedBoms",
request.getBoms().values().stream()
.sorted((a, b) -> a.getOrder().compareTo(b.getOrder()))
.collect(Collectors.toList()));
model.put("reversedBoms",
request.getBoms().values().stream()
.sorted((a, b) -> -a.getOrder().compareTo(b.getOrder()))
.collect(Collectors.toList()));
model.put("compileDependencies",
filterDependencies(dependencies, Dependency.SCOPE_COMPILE));
@ -363,12 +382,35 @@ public class ProjectGenerator {
}
});
Map<String, String> versions = new LinkedHashMap<String, String>();
model.put("buildPropertiesVersions", versions.entrySet());
request.getBuildProperties().getVersions().forEach((k,v) -> {
versions.put(k, v.get());
});
Map<String, String> gradle = new LinkedHashMap<String, String>();
model.put("buildPropertiesGradle", gradle.entrySet());
request.getBuildProperties().getGradle().forEach((k,v) -> {
gradle.put(k, v.get());
});
Map<String, String> maven = new LinkedHashMap<String, String>();
model.put("buildPropertiesMaven", maven.entrySet());
request.getBuildProperties().getMaven().forEach((k,v) -> {
maven.put(k, v.get());
});
// Add various versions
model.put("dependencyManagementPluginVersion", metadata.getConfiguration()
.getEnv().getGradle().getDependencyManagementPluginVersion());
model.put("kotlinVersion",
metadata.getConfiguration().getEnv().getKotlin().getVersion());
if ("kotlin".equals(request.getLanguage())) {
model.put("kotlin", true);
}
if ("groovy".equals(request.getLanguage())) {
model.put("groovy", true);
}
model.put("isRelease", request.getBootVersion().contains("RELEASE"));
// @SpringBootApplication available as from 1.2.0.RC1
model.put("useSpringBootApplication", VERSION_1_2_0_RC1
.compareTo(Version.safeParse(request.getBootVersion())) <= 0);
@ -397,6 +439,9 @@ public class ProjectGenerator {
bean.getPropertyValue(descriptor.getName()));
}
}
if (!request.getBoms().isEmpty()) {
model.put("hasBoms", true);
}
return model;
}
@ -444,6 +489,10 @@ public class ProjectGenerator {
return "maven".equals(request.getBuild());
}
private static boolean isWar(ProjectRequest request) {
return "war".equals(request.getPackaging());
}
private static boolean isNewTestInfrastructureAvailable(ProjectRequest request) {
return VERSION_1_4_0_M2
.compareTo(Version.safeParse(request.getBootVersion())) <= 0;
@ -459,11 +508,11 @@ public class ProjectGenerator {
}
private byte[] doGenerateMavenPom(Map<String, Object> model) {
return groovyTemplate.process("starter-pom.xml", model).getBytes();
return templateRenderer.process("starter-pom.xml", model).getBytes();
}
private byte[] doGenerateGradleBuild(Map<String, Object> model) {
return groovyTemplate.process("starter-build.gradle", model).getBytes();
return templateRenderer.process("starter-build.gradle", model).getBytes();
}
private void writeGradleWrapper(File dir, Version bootVersion) {
@ -525,9 +574,7 @@ public class ProjectGenerator {
}
public void write(File target, String templateName, Map<String, Object> model) {
String tmpl = templateName.endsWith(".groovy") ? templateName + ".tmpl"
: templateName;
String body = groovyTemplate.process(tmpl, model);
String body = templateRenderer.process(templateName, model);
writeText(target, body);
}

View File

@ -151,7 +151,8 @@ public class BillOfMaterials {
* is defined, this returns the reference for the property. Otherwise this returns the
* plain {@link #version}
*/
public String determineVersionToken() {
@JsonIgnore
public String getVersionToken() {
return (versionProperty != null ? "${" + versionProperty + "}" : version);
}

View File

@ -333,7 +333,7 @@ public class InitializrConfiguration {
/**
* Version of the "dependency-management-plugin" to use.
*/
private String dependencyManagementPluginVersion;
private String dependencyManagementPluginVersion = "1.0.0.RELEASE";
private void merge(Gradle other) {
dependencyManagementPluginVersion = other.dependencyManagementPluginVersion;

View File

@ -16,39 +16,41 @@
package io.spring.initializr.util;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import org.codehaus.groovy.control.CompilationFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StreamUtils;
import groovy.lang.Writable;
import groovy.text.GStringTemplateEngine;
import groovy.text.Template;
import groovy.text.TemplateEngine;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Mustache.Compiler;
import com.samskivert.mustache.Mustache.TemplateLoader;
import com.samskivert.mustache.Template;
/**
* @author Dave Syer
*/
public class GroovyTemplate {
public class TemplateRenderer {
private static final Logger log = LoggerFactory.getLogger(TemplateRenderer.class);
private boolean cache = true;
private final TemplateEngine engine;
private final Compiler mustache;
private final ConcurrentMap<String, Template> templateCaches = new ConcurrentReferenceHashMap<>();
public GroovyTemplate(TemplateEngine engine) {
this.engine = engine;
public TemplateRenderer(Compiler mustache) {
this.mustache = mustache;
}
public GroovyTemplate() {
this(new GStringTemplateEngine());
public TemplateRenderer() {
this(mustacheCompiler());
}
public boolean isCache() {
@ -62,18 +64,15 @@ public class GroovyTemplate {
public String process(String name, Map<String, ?> model) {
try {
Template template = getTemplate(name);
Writable writable = template.make(model);
StringWriter result = new StringWriter();
writable.writeTo(result);
return result.toString();
return template.execute(model);
}
catch (Exception e) {
log.error("Cannot render: " + name, e);
throw new IllegalStateException("Cannot render template", e);
}
}
public Template getTemplate(String name)
throws CompilationFailedException, ClassNotFoundException, IOException {
public Template getTemplate(String name) {
if (cache) {
return this.templateCaches.computeIfAbsent(name, n -> loadTemplate(n));
}
@ -82,23 +81,28 @@ public class GroovyTemplate {
protected Template loadTemplate(String name) {
try {
File file = new File("templates", name);
if (file.exists()) {
return engine.createTemplate(file);
}
ClassLoader classLoader = GroovyTemplate.class.getClassLoader();
URL resource = classLoader.getResource("templates/" + name);
if (resource != null) {
return engine.createTemplate(StreamUtils
.copyToString(resource.openStream(), Charset.forName("UTF-8")));
}
return engine.createTemplate(name);
Reader template;
template = mustache.loader.getTemplate(name);
return mustache.compile(template);
}
catch (Exception e) {
throw new IllegalStateException("Cannot load template " + name, e);
}
}
private static Compiler mustacheCompiler() {
return Mustache.compiler().withLoader(mustacheTemplateLoader());
}
private static TemplateLoader mustacheTemplateLoader() {
ResourceLoader resourceLoader = new DefaultResourceLoader();
String prefix = "classpath:/templates/";
Charset charset = Charset.forName("UTF-8");
TemplateLoader loader = name -> {
return new InputStreamReader(
resourceLoader.getResource(prefix + name).getInputStream(), charset);
};
return loader;
}
}

View File

@ -0,0 +1,26 @@
package {{packageName}}
import org.springframework.boot.SpringApplication
{{#useSpringBootApplication}}
import org.springframework.boot.autoconfigure.SpringBootApplication
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
{{/useSpringBootApplication}}
{{#useSpringBootApplication}}
@SpringBootApplication
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
@Configuration
@ComponentScan
@EnableAutoConfiguration
{{/useSpringBootApplication}}
class {{applicationName}} {
static void main(String[] args) {
SpringApplication.run {{applicationName}}, args
}
}

View File

@ -1,18 +0,0 @@
package ${packageName}
import org.springframework.boot.SpringApplication<% if (useSpringBootApplication) { %>
import org.springframework.boot.autoconfigure.SpringBootApplication<% } else { %>
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration<% } %>
<% if (useSpringBootApplication) { %>
@SpringBootApplication<% } else { %>
@Configuration
@ComponentScan
@EnableAutoConfiguration <% } %>
class ${applicationName} {
static void main(String[] args) {
SpringApplication.run ${applicationName}, args
}
}

View File

@ -1,18 +1,26 @@
package ${packageName};
package {{packageName}};
import org.springframework.boot.SpringApplication;<% if (useSpringBootApplication) { %>
import org.springframework.boot.autoconfigure.SpringBootApplication;<% } else { %>
import org.springframework.boot.SpringApplication;
{{#useSpringBootApplication}}
import org.springframework.boot.autoconfigure.SpringBootApplication;
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;<% } %>
<% if (useSpringBootApplication) { %>
@SpringBootApplication<% } else { %>
import org.springframework.context.annotation.Configuration;
{{/useSpringBootApplication}}
{{#useSpringBootApplication}}
@SpringBootApplication
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
@Configuration
@ComponentScan
@EnableAutoConfiguration <% } %>
public class ${applicationName} {
@EnableAutoConfiguration
{{/useSpringBootApplication}}
public class {{applicationName}} {
public static void main(String[] args) {
SpringApplication.run(${applicationName}.class, args);
SpringApplication.run({{applicationName}}.class, args);
}
}

View File

@ -1,17 +1,25 @@
package ${packageName}
package {{packageName}}
import org.springframework.boot.SpringApplication<% if (useSpringBootApplication) { %>
import org.springframework.boot.autoconfigure.SpringBootApplication<% } else { %>
import org.springframework.boot.SpringApplication
{{#useSpringBootApplication}}
import org.springframework.boot.autoconfigure.SpringBootApplication
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration<% } %>
<% if (useSpringBootApplication) { %>
@SpringBootApplication<% } else { %>
import org.springframework.context.annotation.Configuration
{{/useSpringBootApplication}}
{{#useSpringBootApplication}}
@SpringBootApplication
{{/useSpringBootApplication}}
{{^useSpringBootApplication}}
@Configuration
@ComponentScan
@EnableAutoConfiguration <% } %>
class ${applicationName}
@EnableAutoConfiguration
{{/useSpringBootApplication}}
class {{applicationName}}
fun main(args: Array<String>) {
SpringApplication.run(${applicationName}::class.java, *args)
SpringApplication.run({{applicationName}}::class.java, *args)
}

View File

@ -0,0 +1,20 @@
package {{packageName}}
import org.junit.Test
import org.junit.runner.RunWith
{{testImports}}
{{#newTestInfrastructure}}
@RunWith(SpringRunner)
@SpringBootTest
{{/newTestInfrastructure}}
{{^newTestInfrastructure}}
@RunWith(SpringJUnit4ClassRunner)
@SpringApplicationConfiguration(classes = {{applicationName}})
{{/newTestInfrastructure}}
{{testAnnotations}}class {{applicationName}}Tests {
@Test
void contextLoads() {
}
}

View File

@ -1,16 +0,0 @@
package ${packageName}
import org.junit.Test
import org.junit.runner.RunWith
${testImports}<% if (newTestInfrastructure) { %>
@RunWith(SpringRunner)
@SpringBootTest<% } else { %>
@RunWith(SpringJUnit4ClassRunner)
@SpringApplicationConfiguration(classes = ${applicationName})<% } %>
${testAnnotations}class ${applicationName}Tests {
@Test
void contextLoads() {
}
}

View File

@ -1,13 +1,17 @@
package ${packageName};
package {{packageName}};
import org.junit.Test;
import org.junit.runner.RunWith;
${testImports}<% if (newTestInfrastructure) { %>
{{testImports}}
{{#newTestInfrastructure}}
@RunWith(SpringRunner.class)
@SpringBootTest<% } else { %>
@SpringBootTest
{{/newTestInfrastructure}}
{{^newTestInfrastructure}}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ${applicationName}.class)<% } %>
${testAnnotations}public class ${applicationName}Tests {
@SpringApplicationConfiguration(classes = {{applicationName}}.class)
{{/newTestInfrastructure}}
{{testAnnotations}}public class {{applicationName}}Tests {
@Test
public void contextLoads() {

View File

@ -1,13 +1,17 @@
package ${packageName}
package {{packageName}}
import org.junit.Test
import org.junit.runner.RunWith
${testImports}<% if (newTestInfrastructure) { %>
{{testImports}}
{{#newTestInfrastructure}}
@RunWith(SpringRunner::class)
@SpringBootTest<% } else { %>
@SpringBootTest
{{/newTestInfrastructure}}
{{^newTestInfrastructure}}
@RunWith(SpringJUnit4ClassRunner::class)
@SpringApplicationConfiguration(classes = arrayOf(${applicationName}::class))<% } %>
${testAnnotations}class ${applicationName}Tests {
@SpringApplicationConfiguration(classes = arrayOf({{applicationName}}::class))
{{/newTestInfrastructure}}
{{testAnnotations}}class {{applicationName}}Tests {
@Test
fun contextLoads() {

View File

@ -1,14 +1,18 @@
package ${packageName}
package {{packageName}}
import org.springframework.boot.builder.SpringApplicationBuilder<% if (newServletInitializer) { %>
import org.springframework.boot.web.support.SpringBootServletInitializer<% } else { %>
import org.springframework.boot.context.web.SpringBootServletInitializer<% } %>
import org.springframework.boot.builder.SpringApplicationBuilder
{{#newServletInitializer}}
import org.springframework.boot.web.support.SpringBootServletInitializer
{{/newServletInitializer}}
{{^newServletInitializer}}
import org.springframework.boot.context.web.SpringBootServletInitializer
{{/newServletInitializer}}
class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
application.sources(${applicationName})
application.sources({{applicationName}})
}
}

View File

@ -1,14 +1,18 @@
package ${packageName};
package {{packageName}};
import org.springframework.boot.builder.SpringApplicationBuilder;<% if (newServletInitializer) { %>
import org.springframework.boot.web.support.SpringBootServletInitializer;<% } else { %>
import org.springframework.boot.context.web.SpringBootServletInitializer;<% } %>
import org.springframework.boot.builder.SpringApplicationBuilder;
{{#newServletInitializer}}
import org.springframework.boot.web.support.SpringBootServletInitializer;
{{/newServletInitializer}}
{{^newServletInitializer}}
import org.springframework.boot.context.web.SpringBootServletInitializer;
{{/newServletInitializer}}
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(${applicationName}.class);
return application.sources({{applicationName}}.class);
}
}

View File

@ -1,13 +1,17 @@
package ${packageName}
package {{packageName}}
import org.springframework.boot.builder.SpringApplicationBuilder<% if (newServletInitializer) { %>
import org.springframework.boot.web.support.SpringBootServletInitializer<% } else { %>
import org.springframework.boot.context.web.SpringBootServletInitializer<% } %>
import org.springframework.boot.builder.SpringApplicationBuilder
{{#newServletInitializer}}
import org.springframework.boot.web.support.SpringBootServletInitializer
{{/newServletInitializer}}
{{^newServletInitializer}}
import org.springframework.boot.context.web.SpringBootServletInitializer
{{/newServletInitializer}}
class ServletInitializer : SpringBootServletInitializer() {
override fun configure(application: SpringApplicationBuilder) : SpringApplicationBuilder {
return application.sources(${applicationName}::class.java)
return application.sources({{applicationName}}::class.java)
}
}

View File

@ -1,11 +1,11 @@
${logo}
:: Service capabilities :: ${serviceUrl}
{{{logo}}}
:: Service capabilities :: {{serviceUrl}}
Supported dependencies
${dependencies}
{{{dependencies}}}
Project types (* denotes the default)
${types}
{{{types}}}
Parameters
${parameters}
{{{parameters}}}

View File

@ -1,5 +1,5 @@
${logo}
:: Spring Initializr :: ${serviceUrl}
{{{logo}}}
:: Spring Initializr :: {{serviceUrl}}
This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
@ -8,17 +8,17 @@ build system or build structure. See below for further details.
The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
${types}
{{{types}}}
The URI templates take a set of parameters to customize the result of a request
to the linked resource.
${parameters}
{{{parameters}}}
The following section has a list of supported identifiers for the comma-separated
list of "dependencies".
${dependencies}
<% if (hasExamples) { %>
{{{dependencies}}}
{{#hasExamples}}
Examples:
${examples}
<% } %>
{{{examples}}}
{{/hasExamples}}

View File

@ -1,13 +1,13 @@
To create a default demo.zip:
\$ curl ${serviceUrl}/starter.zip -o demo.zip
$ curl {{serviceUrl}}/starter.zip -o demo.zip
To create a web project using Java 7:
\$ curl ${serviceUrl}/starter.zip -d dependencies=web \\
$ curl {{serviceUrl}}/starter.zip -d dependencies=web \\
-d javaVersion=1.7 -o demo.zip
To create a web/data-jpa gradle project unpacked:
\$ curl ${serviceUrl}/starter.tgz -d dependencies=web,data-jpa \\
$ curl {{serviceUrl}}/starter.tgz -d dependencies=web,data-jpa \\
-d type=gradle-project -d baseDir=my-dir | tar -xzvf -
To generate a Maven POM with war packaging:
\$ curl ${serviceUrl}/pom.xml -d packaging=war -o pom.xml
$ curl {{serviceUrl}}/pom.xml -d packaging=war -o pom.xml

View File

@ -1,7 +1,12 @@
<% if (build=='maven') { %>target/
!.mvn/wrapper/maven-wrapper.jar<% } else { %>.gradle
{{#mavenBuild}}
target/
!.mvn/wrapper/maven-wrapper.jar
{{/mavenBuild}}
{{^mavenBuild}}
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar<% } %>
!gradle/wrapper/gradle-wrapper.jar
{{/mavenBuild}}
### STS ###
.apt_generated

View File

@ -1,13 +1,13 @@
To create a default project:
\$ http ${serviceUrl}/starter.zip -d
$ http {{serviceUrl}}/starter.zip -d
To create a web project using Java 7:
\$ http ${serviceUrl}/starter.zip dependencies==web \\
$ http {{serviceUrl}}/starter.zip dependencies==web \\
javaVersion==1.7 -d
To create a web/data-jpa gradle project unpacked:
\$ http ${serviceUrl}/starter.tgz dependencies==web,data-jpa \\
$ http {{serviceUrl}}/starter.tgz dependencies==web,data-jpa \\
type==gradle-project baseDir==my-dir | tar -xzvf -
To generate a Maven POM with war packaging:
\$ http ${serviceUrl}/pom.xml packaging==war -o pom.xml
$ http {{serviceUrl}}/pom.xml packaging==war -o pom.xml

View File

@ -1,61 +1,104 @@
buildscript {
ext {<% buildProperties.gradle.each { %>
${it.key} = '${((java.util.function.Supplier)it.value).get()}'<% } %>
ext {
{{#buildPropertiesGradle}}
{{key}} = '{{value}}'
{{/buildPropertiesGradle}}
}
repositories {
mavenCentral()<% if (!bootVersion.contains("RELEASE")) { %>
mavenCentral()
{{^isRelease}}
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }<% } %>
maven { url "https://repo.spring.io/milestone" }
{{/isRelease}}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:\${springBootVersion}")<% if (!bootOneThreeAvailable) { %>
classpath('io.spring.gradle:dependency-management-plugin:${dependencyManagementPluginVersion}')<% } %><% if (language=='kotlin') { %>
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:\${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:\${kotlinVersion}")<% } %>
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
{{^bootOneThreeAvailable}}
classpath('io.spring.gradle:dependency-management-plugin:{{dependencyManagementPluginVersion}}')
{{/bootOneThreeAvailable}}
{{#kotlin}}
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
{{/kotlin}}
}
}
apply plugin: '${language}'<% if (language=='kotlin') { %>
apply plugin: 'kotlin-spring'<% } %><% if (packaging=='war') { %>
apply plugin: 'eclipse-wtp'<% } else { %>
apply plugin: 'eclipse'<% } %>
apply plugin: '${springBootPluginName}'<% if (!bootOneThreeAvailable) { %>
apply plugin: 'io.spring.dependency-management'<% } %><% if (packaging=='war') { %>
apply plugin: 'war'<% } %>
apply plugin: '{{language}}'
{{#kotlin}}
apply plugin: 'kotlin-spring'
{{/kotlin}}
{{#war}}
apply plugin: 'eclipse-wtp'
{{/war}}
{{^war}}
apply plugin: 'eclipse'
{{/war}}
apply plugin: '{{springBootPluginName}}'
{{^bootOneThreeAvailable}}
apply plugin: 'io.spring.dependency-management'
{{/bootOneThreeAvailable}}
{{#war}}
apply plugin: 'war'
{{/war}}
<% if (packaging=='war') { %>war<% } else { %>jar<% } %> {
baseName = '${artifactId}'
version = '${version}'
{{#war}}war{{/war}}{{^war}}jar{{/war}} {
baseName = '{{artifactId}}'
version = '{{version}}'
}
sourceCompatibility = ${javaVersion}
sourceCompatibility = {{javaVersion}}
repositories {
mavenCentral()<% if (repositories) { repositories.each { key, repo -> %>
maven { url "${repo.url}" }<% }} %>
mavenCentral()
{{#repositoryValues}}
maven { url "{{value.url}}" }
{{/repositoryValues}}
}
<% if (providedDependencies) { %>configurations {
{{#providedDependencies}}
configurations {
providedRuntime
}
<% } %><% if (buildProperties.versions) { %><%buildProperties.versions.each { %>
ext['${it.key}'] = '${((java.util.function.Supplier)it.value).get()}'<% } %>
<% } %>
dependencies {<% compileDependencies.each { %>
compile('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %><% if (language=='groovy') { %>
compile('org.codehaus.groovy:groovy')<% } %><% if (language=='kotlin') { %>
compile("org.jetbrains.kotlin:kotlin-stdlib:\${kotlinVersion}")
compile("org.jetbrains.kotlin:kotlin-reflect:\${kotlinVersion}")<% } %><% runtimeDependencies.each { %>
runtime('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %><% compileOnlyDependencies.each { %>
compileOnly('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %><% providedDependencies.each { %>
providedRuntime('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %>
testCompile('org.springframework.boot:spring-boot-starter-test')<% testDependencies.each { %>
testCompile('${it.groupId}:${it.artifactId}${it.version ? ":$it.version" : ""}${it.type ? "@$it.type" : ""}')<% } %>
{{/providedDependencies}}
{{^buildPropertiesVersions.empty}}
{{#buildPropertiesVersions}}
ext['{{key}}'] = '{{value}}'
{{/buildPropertiesVersions}}
{{/buildPropertiesVersions.empty}}
dependencies {
{{#compileDependencies}}
compile('{{groupId}}:{{artifactId}}{{#version}}:{{version}}{{/version}}{{#type}}@{{type}}{{/type}}')
{{/compileDependencies}}
{{#groovy}}
compile('org.codehaus.groovy:groovy')
{{/groovy}}
{{#kotlin}}
compile("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
{{/kotlin}}
{{#runtimeDependencies}}
runtime('{{groupId}}:{{artifactId}}{{#version}}:{{version}}{{/version}}{{#type}}@{{type}}{{/type}}')
{{/runtimeDependencies}}
{{#compileOnlyDependencies}}
compileOnly('{{groupId}}:{{artifactId}}{{#version}}:{{version}}{{/version}}{{#type}}@{{type}}{{/type}}')
{{/compileOnlyDependencies}}
{{#providedDependencies}}
providedRuntime('{{groupId}}:{{artifactId}}{{#version}}:{{version}}{{/version}}{{#type}}@{{type}}{{/type}}')
{{/providedDependencies}}
testCompile('org.springframework.boot:spring-boot-starter-test')
{{#testDependencies}}
testCompile('{{groupId}}:{{artifactId}}{{#version}}:{{version}}{{/version}}{{#type}}@{{type}}{{/type}}')
{{/testDependencies}}
}
<% if (boms) { %>
{{#hasBoms}}
dependencyManagement {
imports {<% resolvedBoms.reverse().each { %>
mavenBom "${it.groupId}:${it.artifactId}:${it.determineVersionToken()}"<% } %>
imports {
{{#reversedBoms}}
mavenBom "{{groupId}}:{{artifactId}}:{{versionToken}}"
{{/reversedBoms}}
}
}
<% } %>
{{/hasBoms}}

View File

@ -3,103 +3,148 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<packaging>${packaging}</packaging>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{version}}</version>
<packaging>{{packaging}}</packaging>
<name>${name}</name>
<description>${description}</description>
<name>{{name}}</name>
<description>{{description}}</description>
<parent>
<groupId>${mavenParentGroupId}</groupId>
<artifactId>${mavenParentArtifactId}</artifactId>
<version>${mavenParentVersion}</version>
<groupId>{{mavenParentGroupId}}</groupId>
<artifactId>{{mavenParentArtifactId}}</artifactId>
<version>{{mavenParentVersion}}</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties><% buildProperties.maven.each { %>
<${it.key}>${((java.util.function.Supplier)it.value).get()}</${it.key}><% } %><%buildProperties.versions.each { %>
<${it.key}>${((java.util.function.Supplier)it.value).get()}</${it.key}><%}%>
<properties>
{{#buildPropertiesMaven}}
<{{key}}>{{#value}}{{.}}{{/value}}</{{key}}>
{{/buildPropertiesMaven}}
{{#buildPropertiesVersions}}
<{{key}}>{{#value}}{{.}}{{/value}}</{{key}}>
{{/buildPropertiesVersions}}
</properties>
<dependencies><% compileDependencies.each { %>
<dependencies>
{{#compileDependencies}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId><% if (it.version != null) { %>
<version>${it.version}</version><% } %><% if (it.type != null) { %>
<type>${it.type}</type><% } %>
</dependency><% } %><% if (language=='groovy') { %>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
{{#version}}
<version>{{version}}</version>
{{/version}}
{{#type}}
<type>{{type}}</type>
{{/type}}
</dependency>
{{/compileDependencies}}
{{#groovy}}
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency><% } %><% if (language=='kotlin') { %>
</dependency>
{{/groovy}}
{{#kotlin}}
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>\${kotlin.version}</version>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>\${kotlin.version}</version>
</dependency><% } %>
<% runtimeDependencies.each { %>
<version>${kotlin.version}</version>
</dependency>
{{/kotlin}}
{{#runtimeDependencies}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId><% if (it.version != null) { %>
<version>${it.version}</version><% } %>
<scope>runtime</scope><% if (it.type != null) { %>
<type>${it.type}</type><% } %>
</dependency><% } %><% compileOnlyDependencies.each { %>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
{{#version}}
<version>{{version}}</version>
{{/version}}
<scope>runtime</scope>
{{#type}}
<type>{{type}}</type>
{{/type}}
</dependency>
{{/runtimeDependencies}}
{{#compileOnlyDependencies}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId><% if (it.version != null) { %>
<version>${it.version}</version><% } %>
<optional>true</optional><% if (it.type != null) { %>
<type>${it.type}</type><% } %>
</dependency><% } %><% providedDependencies.each { %>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
{{#version}}
<version>{{version}}</version>
{{/version}}
<optional>true</optional>
{{#type}}
<type>{{type}}</type>
{{/type}}
</dependency>
{{/compileOnlyDependencies}}
{{#providedDependencies}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId><% if (it.version != null) { %>
<version>${it.version}</version><% } %>
<scope>provided</scope><% if (it.type != null) { %>
<type>${it.type}</type><% } %>
</dependency><% } %>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
{{#version}}
<version>{{version}}</version>
{{/version}}
<scope>provided</scope>
{{#type}}
<type>{{type}}</type>
{{/type}}
</dependency>
{{/providedDependencies}}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency><% testDependencies.each { %>
</dependency>
{{#testDependencies}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId><% if (it.version != null) { %>
<version>${it.version}</version><% } %>
<scope>test</scope><% if (it.type != null) { %>
<type>${it.type}</type><% } %>
</dependency><% } %>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
{{#version}}
<version>{{version}}</version>
{{/version}}
<scope>test</scope>
{{#type}}
<type>{{type}}</type>
{{/type}}
</dependency>
{{/testDependencies}}
</dependencies>
<% if (boms) { %>
{{#hasBoms}}
<dependencyManagement>
<dependencies><% resolvedBoms.each { %>
<dependencies>
{{#resolvedBoms}}
<dependency>
<groupId>${it.groupId}</groupId>
<artifactId>${it.artifactId}</artifactId>
<version>${it.determineVersionToken()}</version>
<groupId>{{groupId}}</groupId>
<artifactId>{{artifactId}}</artifactId>
<version>{{versionToken}}</version>
<type>pom</type>
<scope>import</scope>
</dependency><% } %>
</dependency>
{{/resolvedBoms}}
</dependencies>
</dependencyManagement>
<% } %>
<build><% if (language=='kotlin') { %>
<sourceDirectory>\${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>\${project.basedir}/src/test/kotlin</testSourceDirectory><% } %>
{{/hasBoms}}
<build>
{{#kotlin}}
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
{{/kotlin}}
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin><% if (language=='groovy') { %>
</plugin>
{{#groovy}}
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
@ -118,11 +163,13 @@
</goals>
</execution>
</executions>
</plugin><% } %><% if (language=='kotlin') { %>
</plugin>
{{/groovy}}
{{#kotlin}}
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>\${kotlin.version}</version>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<plugin>spring</plugin>
@ -148,23 +195,30 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>\${kotlin.version}</version>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin><% } %>
</plugin>
{{/kotlin}}
</plugins>
</build>
<% if (repositories) { %>
<repositories><% repositories.each { key, repo -> %>
{{#hasRepositories}}
<repositories>
{{#repositoryValues}}
<repository>
<id>${key}</id>
<name>${repo.name}</name>
<url>${repo.url}</url>
<id>{{key}}</id>
<name>{{value.name}}</name>
<url>{{value.url}}</url>
<snapshots>
<enabled>${repo.snapshotsEnabled}</enabled>
<enabled>{{value.snapshotsEnabled}}</enabled>
</snapshots>
</repository><% } %>
</repositories><% } %><% if (!bootVersion.contains("RELEASE")) { %>
</repository>
{{/repositoryValues}}
</repositories>
{{/hasRepositories}}
{{^isRelease}}
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
@ -182,6 +236,8 @@
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories><% } %>
</pluginRepositories>
{{/isRelease}}
</project>

View File

@ -16,24 +16,30 @@
package io.spring.initializr.generator;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import io.spring.initializr.metadata.Dependency;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.Type;
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
import io.spring.initializr.util.GroovyTemplate;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import io.spring.initializr.util.TemplateRenderer;
/**
* @author Stephane Nicoll
*/
public class CommandLineHelpGeneratorTests {
private CommandLineHelpGenerator generator = new CommandLineHelpGenerator(
new GroovyTemplate());
private CommandLineHelpGenerator generator;
@Before
public void init() {
generator = new CommandLineHelpGenerator(new TemplateRenderer());
}
@Test
public void generateGenericCapabilities() {
@ -79,7 +85,7 @@ public class CommandLineHelpGeneratorTests {
assertThat(content, containsString("id-b | depB"));
assertThat(content, containsString("https://fake-service"));
assertThat(content, containsString("Examples:"));
assertThat(content, containsString("curl"));
assertThat(content, containsString("curl https://fake-service"));
}
@Test

View File

@ -57,7 +57,7 @@ public class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
@Test
public void defaultGradleBuild() {
ProjectRequest request = createProjectRequest("web");
generateGradleBuild(request);
generateGradleBuild(request).doesNotContain("import");
verifyProjectSuccessfulEventFor(request);
}
@ -167,8 +167,9 @@ public class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
request.setPackaging("war");
request.setType("gradle-project");
generateProject(request).isJavaWarProject().isGradleProject().gradleBuildAssert()
.contains("compile('org.foo:thymeleaf')") // This is tagged as web facet
// so it brings the web one
// This is tagged as web facet so it brings the web one
.contains("compile('org.foo:thymeleaf')").contains("war {")
.contains("compile('org.foo:thymeleaf')").contains("apply plugin: 'war'")
.doesNotContain(
"compile('org.springframework.boot:spring-boot-starter-web')")
.contains(

View File

@ -46,7 +46,7 @@ public class SourceCodeAssert {
try (InputStream stream = expected.getInputStream()) {
String expectedContent = StreamUtils.copyToString(stream,
Charset.forName("UTF-8"));
assertEquals("Unexpected content for $name",
assertEquals("Unexpected content for " + name,
expectedContent.replaceAll("\r\n", "\n"), content);
}
catch (IOException e) {

View File

@ -48,7 +48,7 @@ import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataBuilder;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.metadata.InitializrProperties;
import io.spring.initializr.util.GroovyTemplate;
import io.spring.initializr.util.TemplateRenderer;
import io.spring.initializr.web.project.MainController;
import io.spring.initializr.web.support.DefaultDependencyMetadataProvider;
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider;
@ -81,11 +81,11 @@ public class InitializrAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MainController initializrMainController(InitializrMetadataProvider metadataProvider,
GroovyTemplate groovyTemplate,
TemplateRenderer templateRenderer,
ResourceUrlProvider resourceUrlProvider,
ProjectGenerator projectGenerator,
DependencyMetadataProvider dependencyMetadataProvider) {
return new MainController(metadataProvider, groovyTemplate, resourceUrlProvider
return new MainController(metadataProvider, templateRenderer, resourceUrlProvider
, projectGenerator, dependencyMetadataProvider);
}
@ -103,12 +103,12 @@ public class InitializrAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public GroovyTemplate groovyTemplate(Environment environment) {
public TemplateRenderer templateRenderer(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment, "spring.groovy.template.");
boolean cache = resolver.getProperty("cache", Boolean.class, true);
GroovyTemplate groovyTemplate = new GroovyTemplate();
groovyTemplate.setCache(cache);
return groovyTemplate;
TemplateRenderer templateRenderer = new TemplateRenderer();
templateRenderer.setCache(cache);
return templateRenderer;
}
@Bean

View File

@ -57,7 +57,7 @@ import io.spring.initializr.metadata.DependencyMetadataProvider;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.util.Agent;
import io.spring.initializr.util.GroovyTemplate;
import io.spring.initializr.util.TemplateRenderer;
import io.spring.initializr.util.Version;
import io.spring.initializr.web.mapper.DependencyMetadataV21JsonMapper;
import io.spring.initializr.web.mapper.InitializrMetadataJsonMapper;
@ -85,13 +85,13 @@ public class MainController extends AbstractInitializrController {
private final CommandLineHelpGenerator commandLineHelpGenerator;
public MainController(InitializrMetadataProvider metadataProvider,
GroovyTemplate groovyTemplate, ResourceUrlProvider resourceUrlProvider,
TemplateRenderer templateRenderer, ResourceUrlProvider resourceUrlProvider,
ProjectGenerator projectGenerator,
DependencyMetadataProvider dependencyMetadataProvider) {
super(metadataProvider, resourceUrlProvider);
this.projectGenerator = projectGenerator;
this.dependencyMetadataProvider = dependencyMetadataProvider;
this.commandLineHelpGenerator = new CommandLineHelpGenerator(groovyTemplate);
this.commandLineHelpGenerator = new CommandLineHelpGenerator(templateRenderer);
}
@ModelAttribute

View File

@ -409,8 +409,8 @@ public class MainControllerIntegrationTests
@Test
public void homeHasBootVersion() {
String body = htmlHome();
assertTrue("Wrong body:\n$body", body.contains("name=\"bootVersion\""));
assertTrue("Wrong body:\n$body", body.contains("1.2.0.BUILD-SNAPSHOT\""));
assertTrue("Wrong body:\n" + body, body.contains("name=\"bootVersion\""));
assertTrue("Wrong body:\n" + body, body.contains("1.2.0.BUILD-SNAPSHOT\""));
}
@Test

View File

@ -34,7 +34,7 @@
"fallbackApplicationName": "Application",
"forceSsl": true,
"gradle": {
"dependencyManagementPluginVersion": null
"dependencyManagementPluginVersion": "1.0.0.RELEASE"
},
"kotlin": {
"version": null

11
pom.xml
View File

@ -97,17 +97,6 @@
<artifactId>xmlunit</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.gebish</groupId>
<artifactId>geb-core</artifactId>
<version>0.10.0</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.rauschig</groupId>
<artifactId>jarchivelib</artifactId>