mirror of
https://gitee.com/dcren/initializr.git
synced 2025-07-17 01:46:19 +08:00
Add project request post processing
This commit introduces `ProjectRequestPostProcessor` as a mean to modify an incoming `ProjectRequest` before and after its resolution against the meta-data. By default, all beans of that type are invoked automatically and they are ordered against their `@Order` or `Ordered` settings. Closes gh-260
This commit is contained in:
parent
fb7b8eb5cb
commit
56210d9bf2
@ -55,6 +55,9 @@ class ProjectGenerator {
|
|||||||
@Autowired
|
@Autowired
|
||||||
InitializrMetadataProvider metadataProvider
|
InitializrMetadataProvider metadataProvider
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ProjectRequestResolver requestResolver
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
ProjectResourceLocator projectResourceLocator = new ProjectResourceLocator()
|
ProjectResourceLocator projectResourceLocator = new ProjectResourceLocator()
|
||||||
|
|
||||||
@ -210,12 +213,12 @@ class ProjectGenerator {
|
|||||||
* @param request the request to handle
|
* @param request the request to handle
|
||||||
* @return a model for that request
|
* @return a model for that request
|
||||||
*/
|
*/
|
||||||
protected Map resolveModel(ProjectRequest request) {
|
protected Map resolveModel(ProjectRequest originalRequest) {
|
||||||
Assert.notNull request.bootVersion, 'boot version must not be null'
|
Assert.notNull originalRequest.bootVersion, 'boot version must not be null'
|
||||||
def model = [:]
|
def model = [:]
|
||||||
def metadata = metadataProvider.get()
|
def metadata = metadataProvider.get()
|
||||||
|
|
||||||
request.resolve(metadata)
|
ProjectRequest request = requestResolver.resolve(originalRequest, metadata)
|
||||||
|
|
||||||
// request resolved so we can log what has been requested
|
// request resolved so we can log what has been requested
|
||||||
def dependencies = request.resolvedDependencies
|
def dependencies = request.resolvedDependencies
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2016 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.generator
|
||||||
|
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project generation hook that allows for custom modification of {@link ProjectRequest}
|
||||||
|
* instances, e.g. adding custom dependencies or forcing certain settings based on custom
|
||||||
|
* logic.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
interface ProjectRequestPostProcessor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this post processor to the given {@code ProjectRequest} <i>before</i> it
|
||||||
|
* gets resolved against the specified {@code InitializrMetadata}.
|
||||||
|
* <p>Consider using this hook to customize basic settings of the {@code request};
|
||||||
|
* for more advanced logic (in particular with regards to dependencies), consider
|
||||||
|
* using {@code postProcessAfterResolution}.
|
||||||
|
* @param request an unresolved {@link ProjectRequest}
|
||||||
|
* @param metadata the metadata to use to resolve this request
|
||||||
|
* @see ProjectRequest#resolve(InitializrMetadata)
|
||||||
|
*/
|
||||||
|
void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this post processor to the given {@code ProjectRequest} <i>after</i> it has
|
||||||
|
* been resolved against the specified {@code InitializrMetadata}.
|
||||||
|
* <p>Dependencies, repositories, bills of materials, default properties and others
|
||||||
|
* aspects of the request will have been resolved prior to invocation. In particular,
|
||||||
|
* note that no further validation checks will be performed.
|
||||||
|
* @param request an resolved {@code ProjectRequest}
|
||||||
|
* @param metadata the metadata that were used to resolve this request
|
||||||
|
*/
|
||||||
|
void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.spring.initializr.generator
|
||||||
|
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of {@link ProjectRequestPostProcessor} with empty methods allowing
|
||||||
|
* sub-classes to override only the methods they're interested in.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class ProjectRequestPostProcessorAdapter implements ProjectRequestPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.spring.initializr.generator
|
||||||
|
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
|
|
||||||
|
import org.springframework.util.Assert
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve {@link ProjectRequest} instances, honoring callback hook points.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class ProjectRequestResolver {
|
||||||
|
|
||||||
|
private final List<ProjectRequestPostProcessor> postProcessors
|
||||||
|
|
||||||
|
ProjectRequestResolver(List<ProjectRequestPostProcessor> postProcessors) {
|
||||||
|
this.postProcessors = new ArrayList<>(postProcessors)
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectRequest resolve(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
Assert.notNull(request, "Request must not be null")
|
||||||
|
applyPostProcessBeforeResolution(request, metadata)
|
||||||
|
request.resolve(metadata)
|
||||||
|
applyPostProcessAfterResolution(request, metadata)
|
||||||
|
request
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyPostProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
for (ProjectRequestPostProcessor processor : postProcessors) {
|
||||||
|
processor.postProcessBeforeResolution(request, metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyPostProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
for (ProjectRequestPostProcessor processor : postProcessors) {
|
||||||
|
processor.postProcessAfterResolution(request, metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -57,6 +57,7 @@ abstract class AbstractProjectGeneratorTests {
|
|||||||
.addDependencyGroup('test', 'security', 'data-jpa', 'aop', 'batch', 'integration').build()
|
.addDependencyGroup('test', 'security', 'data-jpa', 'aop', 'batch', 'integration').build()
|
||||||
applyMetadata(metadata)
|
applyMetadata(metadata)
|
||||||
projectGenerator.eventPublisher = eventPublisher
|
projectGenerator.eventPublisher = eventPublisher
|
||||||
|
projectGenerator.requestResolver = new ProjectRequestResolver([])
|
||||||
projectGenerator.tmpdir = folder.newFolder().absolutePath
|
projectGenerator.tmpdir = folder.newFolder().absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package io.spring.initializr.generator
|
|||||||
|
|
||||||
import io.spring.initializr.metadata.BillOfMaterials
|
import io.spring.initializr.metadata.BillOfMaterials
|
||||||
import io.spring.initializr.metadata.Dependency
|
import io.spring.initializr.metadata.Dependency
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder
|
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -642,6 +643,34 @@ class ProjectGeneratorTests extends AbstractProjectGeneratorTests {
|
|||||||
.doesNotContain('ignore.property')
|
.doesNotContain('ignore.property')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void versionRangeWithPostProcessor() {
|
||||||
|
Dependency foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo')
|
||||||
|
foo.mappings << new Dependency.Mapping(versionRange: '[1.2.0.RELEASE,1.3.0.M1)', version: '1.0.0')
|
||||||
|
foo.mappings << new Dependency.Mapping(versionRange: '1.3.0.M1', version: '1.2.0')
|
||||||
|
def metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||||
|
.addDependencyGroup('foo', foo).build()
|
||||||
|
applyMetadata(metadata)
|
||||||
|
|
||||||
|
// First without processor, get the correct version
|
||||||
|
def request = createProjectRequest('foo')
|
||||||
|
request.bootVersion = '1.2.5.RELEASE'
|
||||||
|
generateMavenPom(request).hasDependency(
|
||||||
|
new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', version: '1.0.0'))
|
||||||
|
|
||||||
|
// First after processor that flips Spring Boot version
|
||||||
|
projectGenerator.requestResolver = new ProjectRequestResolver(Collections.singletonList(
|
||||||
|
new ProjectRequestPostProcessorAdapter() {
|
||||||
|
@Override
|
||||||
|
void postProcessBeforeResolution(ProjectRequest r, InitializrMetadata m) {
|
||||||
|
r.bootVersion = '1.3.0.M2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
generateMavenPom(request).hasDependency(
|
||||||
|
new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', version: '1.2.0'))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void invalidProjectTypeMavenPom() {
|
void invalidProjectTypeMavenPom() {
|
||||||
def request = createProjectRequest('web')
|
def request = createProjectRequest('web')
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package io.spring.initializr.generator
|
||||||
|
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
|
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ProjectRequestResolver}.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class ProjectRequestResolverTests {
|
||||||
|
|
||||||
|
def metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||||
|
.addDependencyGroup('test', 'web', 'security', 'data-jpa')
|
||||||
|
.build()
|
||||||
|
|
||||||
|
final List<ProjectRequestPostProcessor> postProcessors = []
|
||||||
|
final GenericProjectRequestPostProcessor processor = new GenericProjectRequestPostProcessor()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
void setup() {
|
||||||
|
this.postProcessors << processor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void beforeResolution() {
|
||||||
|
processor.before['javaVersion'] = '1.2'
|
||||||
|
ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors)
|
||||||
|
assertEquals '1.2', request.javaVersion
|
||||||
|
assertEquals '1.2', request.buildProperties.versions['java.version'].call()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void afterResolution() {
|
||||||
|
postProcessors << new ProjectRequestPostProcessorAdapter() {
|
||||||
|
@Override
|
||||||
|
void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
request.buildProperties.maven.clear()
|
||||||
|
request.buildProperties.maven['foo'] = { 'bar' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProjectRequest request = resolve(createMavenProjectRequest(), postProcessors)
|
||||||
|
assertEquals 1, request.buildProperties.maven.size()
|
||||||
|
assertEquals 'bar', request.buildProperties.maven['foo'].call()
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectRequest resolve(def request, def processors) {
|
||||||
|
new ProjectRequestResolver(processors)
|
||||||
|
.resolve(request, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectRequest createMavenProjectRequest(String... styles) {
|
||||||
|
def request = createProjectRequest(styles)
|
||||||
|
request.type = 'maven-project'
|
||||||
|
request
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectRequest createProjectRequest(String... styles) {
|
||||||
|
def request = new ProjectRequest()
|
||||||
|
request.initialize(metadata)
|
||||||
|
request.style.addAll Arrays.asList(styles)
|
||||||
|
request
|
||||||
|
}
|
||||||
|
|
||||||
|
static class GenericProjectRequestPostProcessor implements ProjectRequestPostProcessor {
|
||||||
|
|
||||||
|
final Map<String, Object> before = [:]
|
||||||
|
final Map<String, Object> after = [:]
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
before.forEach { k, v -> request.setProperty(k, v) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void postProcessAfterResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
after.forEach { k, v -> request.setProperty(k, v) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,6 +20,8 @@ import java.util.concurrent.TimeUnit
|
|||||||
|
|
||||||
import com.google.common.cache.CacheBuilder
|
import com.google.common.cache.CacheBuilder
|
||||||
import io.spring.initializr.generator.ProjectGenerator
|
import io.spring.initializr.generator.ProjectGenerator
|
||||||
|
import io.spring.initializr.generator.ProjectRequestPostProcessor
|
||||||
|
import io.spring.initializr.generator.ProjectRequestResolver
|
||||||
import io.spring.initializr.generator.ProjectResourceLocator
|
import io.spring.initializr.generator.ProjectResourceLocator
|
||||||
import io.spring.initializr.metadata.DependencyMetadataProvider
|
import io.spring.initializr.metadata.DependencyMetadataProvider
|
||||||
import io.spring.initializr.metadata.InitializrMetadataBuilder
|
import io.spring.initializr.metadata.InitializrMetadataBuilder
|
||||||
@ -30,6 +32,7 @@ import io.spring.initializr.web.support.DefaultDependencyMetadataProvider
|
|||||||
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider
|
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider
|
||||||
import io.spring.initializr.web.ui.UiController
|
import io.spring.initializr.web.ui.UiController
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||||
import org.springframework.cache.CacheManager
|
import org.springframework.cache.CacheManager
|
||||||
@ -56,6 +59,9 @@ import org.springframework.context.annotation.Configuration
|
|||||||
@EnableConfigurationProperties(InitializrProperties)
|
@EnableConfigurationProperties(InitializrProperties)
|
||||||
class InitializrAutoConfiguration {
|
class InitializrAutoConfiguration {
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
List<ProjectRequestPostProcessor> postProcessors = []
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
WebConfig webConfig() {
|
WebConfig webConfig() {
|
||||||
new WebConfig()
|
new WebConfig()
|
||||||
@ -79,6 +85,12 @@ class InitializrAutoConfiguration {
|
|||||||
new ProjectGenerator()
|
new ProjectGenerator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
ProjectRequestResolver projectRequestResolver() {
|
||||||
|
new ProjectRequestResolver(postProcessors)
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ProjectResourceLocator projectResourceLocator() {
|
ProjectResourceLocator projectResourceLocator() {
|
||||||
return new ProjectResourceLocator()
|
return new ProjectResourceLocator()
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package io.spring.initializr.web.project
|
||||||
|
|
||||||
|
import io.spring.initializr.generator.ProjectRequest
|
||||||
|
import io.spring.initializr.generator.ProjectRequestPostProcessor
|
||||||
|
import io.spring.initializr.generator.ProjectRequestPostProcessorAdapter
|
||||||
|
import io.spring.initializr.metadata.InitializrMetadata
|
||||||
|
import io.spring.initializr.web.AbstractInitializrControllerIntegrationTests
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.springframework.boot.test.SpringApplicationConfiguration
|
||||||
|
import org.springframework.context.annotation.Bean
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.core.annotation.Order
|
||||||
|
import org.springframework.test.context.ActiveProfiles
|
||||||
|
|
||||||
|
@ActiveProfiles('test-default')
|
||||||
|
@SpringApplicationConfiguration(classes = [Config, ProjectRequestPostProcessorConfiguration])
|
||||||
|
class ProjectGenerationPostProcessorTests extends AbstractInitializrControllerIntegrationTests {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessorsInvoked() {
|
||||||
|
downloadZip('/starter.zip?bootVersion=1.2.4.RELEASE&javaVersion=1.6')
|
||||||
|
.isJavaProject()
|
||||||
|
.isMavenProject().pomAssert()
|
||||||
|
.hasSpringBootParent('1.2.3.RELEASE')
|
||||||
|
.hasProperty('java.version', '1.7')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class ProjectRequestPostProcessorConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(2)
|
||||||
|
ProjectRequestPostProcessor secondPostProcessor() {
|
||||||
|
new ProjectRequestPostProcessorAdapter() {
|
||||||
|
@Override
|
||||||
|
void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
request.javaVersion = '1.7'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(1)
|
||||||
|
ProjectRequestPostProcessor firstPostProcessor() {
|
||||||
|
new ProjectRequestPostProcessorAdapter() {
|
||||||
|
@Override
|
||||||
|
void postProcessBeforeResolution(ProjectRequest request, InitializrMetadata metadata) {
|
||||||
|
request.javaVersion = '1.2'
|
||||||
|
request.bootVersion = '1.2.3.RELEASE'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user