Switch project structure to use the new generator

This commit removes the former `ProjectGenerator` api based on mustache
template in favour of a new DSL infrastructure to be detailed in further
commits.

Event handling is now web-specific with a `ProjectRequest` and a
`WebProjectRequest` that gathers the base input from the request and
some additional web-specific metadata, respectively. As a consequence
the `initializr-actuator` module has now a dependency on the
`initializr-web` module.

See gh-340

Co-authored-by: Stephane Nicoll <snicoll@pivotal.io>
This commit is contained in:
Madhura Bhave
2018-11-21 15:20:08 +01:00
committed by Stephane Nicoll
parent 0628829cd3
commit e281480426
129 changed files with 1153 additions and 8245 deletions

View File

@@ -19,7 +19,10 @@
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-generator</artifactId>
</dependency>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
@@ -75,11 +78,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.spring.initializr</groupId>
<artifactId>initializr-web</artifactId>

View File

@@ -23,7 +23,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.spring.initializr.actuate.stat.StatsProperties.Elastic;
import io.spring.initializr.generator.ProjectRequestEvent;
import io.spring.initializr.web.project.ProjectRequestEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,12 +24,13 @@ import io.spring.initializr.actuate.stat.ProjectRequestDocument.ClientInformatio
import io.spring.initializr.actuate.stat.ProjectRequestDocument.DependencyInformation;
import io.spring.initializr.actuate.stat.ProjectRequestDocument.ErrorStateInformation;
import io.spring.initializr.actuate.stat.ProjectRequestDocument.VersionInformation;
import io.spring.initializr.generator.ProjectFailedEvent;
import io.spring.initializr.generator.ProjectRequest;
import io.spring.initializr.generator.ProjectRequestEvent;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.util.Agent;
import io.spring.initializr.util.Version;
import io.spring.initializr.web.project.ProjectFailedEvent;
import io.spring.initializr.web.project.ProjectRequest;
import io.spring.initializr.web.project.ProjectRequestEvent;
import io.spring.initializr.web.project.WebProjectRequest;
import org.springframework.util.StringUtils;
@@ -43,7 +44,6 @@ public class ProjectRequestDocumentFactory {
public ProjectRequestDocument createDocument(ProjectRequestEvent event) {
InitializrMetadata metadata = event.getMetadata();
ProjectRequest request = event.getProjectRequest();
ProjectRequestDocument document = new ProjectRequestDocument();
document.setGenerationTimestamp(event.getTimestamp());
document.setGroupId(request.getGroupId());
@@ -118,16 +118,19 @@ public class ProjectRequestDocumentFactory {
}
private ClientInformation determineClientInformation(ProjectRequest request) {
Agent agent = determineAgent(request);
String ip = determineIp(request);
String country = determineCountry(request);
if (agent != null || ip != null || country != null) {
return new ClientInformation(agent, ip, country);
if (request instanceof WebProjectRequest) {
WebProjectRequest webProjectRequest = (WebProjectRequest) request;
Agent agent = determineAgent(webProjectRequest);
String ip = determineIp(webProjectRequest);
String country = determineCountry(webProjectRequest);
if (agent != null || ip != null || country != null) {
return new ClientInformation(agent, ip, country);
}
}
return null;
}
private Agent determineAgent(ProjectRequest request) {
private Agent determineAgent(WebProjectRequest request) {
String userAgent = (String) request.getParameters().get("user-agent");
if (StringUtils.hasText(userAgent)) {
return Agent.fromUserAgent(userAgent);
@@ -135,13 +138,13 @@ public class ProjectRequestDocumentFactory {
return null;
}
private String determineIp(ProjectRequest request) {
private String determineIp(WebProjectRequest request) {
String candidate = (String) request.getParameters().get("cf-connecting-ip");
return (StringUtils.hasText(candidate)) ? candidate
: (String) request.getParameters().get("x-forwarded-for");
}
private String determineCountry(ProjectRequest request) {
private String determineCountry(WebProjectRequest request) {
String candidate = (String) request.getParameters().get("cf-ipcountry");
if (StringUtils.hasText(candidate) && !"xx".equalsIgnoreCase(candidate)) {
return candidate;

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.initializr.actuate.stat;
import io.spring.initializr.generator.ProjectRequest;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataProvider;
import io.spring.initializr.metadata.SimpleInitializrMetadataProvider;
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
/**
* @author Stephane Nicoll
*/
abstract class AbstractInitializrStatTests {
private final InitializrMetadata metadata = InitializrMetadataTestBuilder
.withDefaults().addDependencyGroup("core", "security", "validation", "aop")
.addDependencyGroup("web", "web", "data-rest", "jersey")
.addDependencyGroup("data", "data-jpa", "jdbc")
.addDependencyGroup("database", "h2", "mysql").build();
protected InitializrMetadataProvider createProvider(InitializrMetadata metadata) {
return new SimpleInitializrMetadataProvider(metadata);
}
protected ProjectRequest createProjectRequest() {
ProjectRequest request = new ProjectRequest();
request.initialize(this.metadata);
return request;
}
public InitializrMetadata getMetadata() {
return this.metadata;
}
}

View File

@@ -26,8 +26,11 @@ import java.util.Collections;
import java.util.UUID;
import io.spring.initializr.actuate.stat.StatsProperties.Elastic;
import io.spring.initializr.generator.ProjectGeneratedEvent;
import io.spring.initializr.generator.ProjectRequest;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
import io.spring.initializr.web.project.ProjectGeneratedEvent;
import io.spring.initializr.web.project.ProjectRequest;
import io.spring.initializr.web.project.WebProjectRequest;
import org.json.JSONException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -59,7 +62,13 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
*
* @author Stephane Nicoll
*/
class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
class ProjectGenerationStatPublisherTests {
private final InitializrMetadata metadata = InitializrMetadataTestBuilder
.withDefaults().addDependencyGroup("core", "security", "validation", "aop")
.addDependencyGroup("web", "web", "data-rest", "jersey")
.addDependencyGroup("data", "data-jpa", "jdbc")
.addDependencyGroup("database", "h2", "mysql").build();
private RetryTemplate retryTemplate;
@@ -132,13 +141,13 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.andRespond(withStatus(HttpStatus.CREATED)
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@Test
void publishDocument() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.setGroupId("com.example.acme");
request.setArtifactId("project");
request.setType("maven-project");
@@ -156,7 +165,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -177,7 +186,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -198,7 +207,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -219,7 +228,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -241,7 +250,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -262,7 +271,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -284,7 +293,7 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.body(mockResponse(UUID.randomUUID().toString(), true))
.contentType(MediaType.APPLICATION_JSON));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
@@ -302,12 +311,18 @@ class ProjectGenerationStatPublisherTests extends AbstractInitializrStatTests {
.andExpect(method(HttpMethod.POST))
.andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
this.statPublisher.handleEvent(createProjectGeneratedEvent(request));
handleEvent(request);
this.mockServer.verify();
}
private ProjectGeneratedEvent createProjectGeneratedEvent(ProjectRequest request) {
return new ProjectGeneratedEvent(request, getMetadata());
private WebProjectRequest createProjectRequest() {
WebProjectRequest request = new WebProjectRequest();
request.initialize(this.metadata);
return request;
}
private void handleEvent(ProjectRequest request) {
this.statPublisher.handleEvent(new ProjectGeneratedEvent(request, this.metadata));
}
private static String mockResponse(String id, boolean created) {

View File

@@ -18,9 +18,12 @@ package io.spring.initializr.actuate.stat;
import java.util.Arrays;
import io.spring.initializr.generator.ProjectFailedEvent;
import io.spring.initializr.generator.ProjectGeneratedEvent;
import io.spring.initializr.generator.ProjectRequest;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
import io.spring.initializr.web.project.ProjectFailedEvent;
import io.spring.initializr.web.project.ProjectGeneratedEvent;
import io.spring.initializr.web.project.ProjectRequest;
import io.spring.initializr.web.project.WebProjectRequest;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -30,7 +33,13 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Stephane Nicoll
*/
class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
class ProjectRequestDocumentFactoryTests {
private final InitializrMetadata metadata = InitializrMetadataTestBuilder
.withDefaults().addDependencyGroup("core", "security", "validation", "aop")
.addDependencyGroup("web", "web", "data-rest", "jersey")
.addDependencyGroup("data", "data-jpa", "jdbc")
.addDependencyGroup("database", "h2", "mysql").build();
private final ProjectRequestDocumentFactory factory = new ProjectRequestDocumentFactory();
@@ -58,9 +67,19 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
assertThat(document.getVersion().getMinor()).isEqualTo("2.1");
}
@Test
void createDocumentWithNonWebProjectRequest() {
ProjectRequest request = new ProjectRequest();
request.setBootVersion("2.1.0.RELEASE");
request.setType("maven-build");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
assertThat(document.getClient()).isNull();
}
@Test
void createDocumentWithRequestIp() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("x-forwarded-for", "10.0.0.123");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -70,7 +89,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithRequestIpv6() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("x-forwarded-for", "2001:db8:a0b:12f0::1");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -80,7 +99,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithCloudFlareHeaders() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("cf-connecting-ip", "10.0.0.123");
request.getParameters().put("cf-ipcountry", "BE");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
@@ -91,7 +110,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithCloudFlareIpv6() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("cf-connecting-ip", "2001:db8:a0b:12f0::1");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -101,7 +120,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithCloudFlareHeadersAndOtherHeaders() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("cf-connecting-ip", "10.0.0.123");
request.getParameters().put("x-forwarded-for", "192.168.1.101");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
@@ -112,7 +131,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithCloudFlareCountrySetToXX() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("cf-connecting-ip", "Xx"); // case insensitive
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -121,7 +140,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithUserAgent() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("user-agent", "HTTPie/0.8.0");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -131,7 +150,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithUserAgentNoVersion() {
ProjectRequest request = createProjectRequest();
WebProjectRequest request = createProjectRequest();
request.getParameters().put("user-agent", "IntelliJ IDEA");
ProjectGeneratedEvent event = createProjectGeneratedEvent(request);
ProjectRequestDocument document = this.factory.createDocument(event);
@@ -221,7 +240,7 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
@Test
void createDocumentWithProjectFailedEvent() {
ProjectRequest request = createProjectRequest();
ProjectFailedEvent event = new ProjectFailedEvent(request, getMetadata(),
ProjectFailedEvent event = new ProjectFailedEvent(request, this.metadata,
new IllegalStateException("my test message"));
ProjectRequestDocument document = this.factory.createDocument(event);
assertThat(document.getErrorState().isInvalid()).isTrue();
@@ -233,8 +252,14 @@ class ProjectRequestDocumentFactoryTests extends AbstractInitializrStatTests {
assertThat(document.getErrorState().getMessage()).isEqualTo("my test message");
}
private WebProjectRequest createProjectRequest() {
WebProjectRequest request = new WebProjectRequest();
request.initialize(this.metadata);
return request;
}
private ProjectGeneratedEvent createProjectGeneratedEvent(ProjectRequest request) {
return new ProjectGeneratedEvent(request, getMetadata());
return new ProjectGeneratedEvent(request, this.metadata);
}
}