如何将 Embedded PostgreSQL Server Java 组件作为单独的服务使用?
How to use the Embedded PostgreSQL Server Java component as a separate service?
我正在尝试为基于 RESTful(服务)Java 的应用程序创建一个全面的集成测试套件,该应用程序在 Tomcat(7.x) 并依赖于 Postgresql (9.x) 实例。此外,如果可能的话,我希望能够 运行 这个套件作为一个独立的进程,完全来自 maven 3.x,通过使用 maven failsafe 插件。这样,测试就可以 运行 跨越 3 个主要平台(Mac OSX、Linux 和 Windows)。
据我所知,我认为实现这一目标的关键是执行以下步骤(按此顺序):
- 在 maven lifecycle 的预集成测试阶段以某种方式启动 postgresql 数据库(和模式设置)的 "embedded" 版本,postgres-db-process 运行在后台运行
- 启动加载我的服务应用程序的 Java 容器:我正在使用 Jetty 9.1.5 插件
- 运行 我在集成测试阶段从 Failsafe 插件进行的(基于 JUnit 的)测试
- 在 Maven 的 post-集成测试阶段
关闭我的 Jetty 容器
- 最后,有一些机制关闭之前启动的(后台)postgres-db-process post-生命周期的集成-测试阶段(kill/clean-up这个过程)
在我当前的实施中,成功完成了步骤 1 - 3。在第 2 步中,它使用 exec-maven-plugin,它调用使用 postgresql-embedded Java component 的 Java class。
摘自 POM.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>Run Postgres DB start/schema setup</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.some.package.test.utils.DbSetup</mainClass>
<arguments>
<argument>setup</argument>
</arguments>
</configuration>
</plugin>
这里是 DBSetup class 的摘录,它使用 postgresql-embedded 来启动 postgresql 实例:
try {
DownloadConfigBuilder downloadConfigBuilder = new DownloadConfigBuilder();
downloadConfigBuilder.defaultsForCommand(Command.Postgres);
downloadConfigBuilder.proxyFactory(new HttpProxyFactory(PROXY_ADDRESS, DEFAULT_PROXY_PORT));
IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
.defaults(Command.Postgres)
.artifactStore(new ArtifactStoreBuilder()
.defaults(Command.Postgres)
.download(downloadConfigBuilder)).build();
PostgresStarter<PostgresExecutable, PostgresProcess> runtime = PostgresStarter.getInstance(runtimeConfig);
final PostgresConfig config = new PostgresConfig(Version.V9_2_4, new AbstractPostgresConfig.Net(
"localhost", 5432
), new AbstractPostgresConfig.Storage(dbName), new AbstractPostgresConfig.Timeout(),
new AbstractPostgresConfig.Credentials(username, password));
config.getAdditionalInitDbParams().addAll(Arrays.asList(
"-E", "UTF-8",
"--locale=en_US.UTF-8",
"--lc-collate=en_US.UTF-8",
"--lc-ctype=en_US.UTF-8"
));
exec = runtime.prepare(config);
process = exec.start();
System.out.println("embedded Postgres started");
Thread.sleep(1200L);
} catch (IOException e) {
System.out.println("Something Went Wrong initializing embedded Postgres: " + e);
e.printStackTrace();
}
catch (InterruptedException e) {
System.out.println("Something Went Wrong Pausing this thread " + e);
e.printStackTrace();
}
请注意,我没有在启动 Postgres 实例的方法中调用 process.stop();
。因此,我目前无法关闭 数据库进程。一旦我退出此 class DbSetup
,所有对该现有进程的引用都将丢失。并且 Postgres 进程永远不会关闭。事实上,jetty 容器似乎也不会关闭,整个 maven 作业都挂了,所以我必须手动杀死它(摘自我的 maven 控制台输出):
[INFO] --- exec-maven-plugin:1.2.1:java (Run Postgres DB start/schema setup) @ BLAHBLAH ---
***START of Postgres DB Setup Process ***
Extract /Users/myUserName/.embedpostgresql/postgresql-9.2.4-1-osx-binaries.zip START
...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................Extract /Users/myUserName/.embedpostgresql/postgresql-9.2.4-1-osx-binaries.zip DONE
INFO:20161021 12:58:00: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[], additionalInitDbParams=[-E, UTF-8, --locale=en_US.UTF-8, --lc-collate=en_US.UTF-8, --lc-ctype=en_US.UTF-8]}
INFO:20161021 12:58:01: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[BLAH], additionalInitDbParams=[]}
INFO:20161021 12:58:04: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[], additionalInitDbParams=[-E, UTF-8, --locale=en_US.UTF-8, --lc-collate=en_US.UTF-8, --lc-ctype=en_US.UTF-8]}
embedded Postgres started
***END of Postgres DB Setup Process ***
...
[INFO] --- jetty-maven-plugin:9.1.2.v20140210:run-war (start-jetty) @ BLAH ---
[INFO] Configuring Jetty for project: BlahProject
[INFO] Context path = /
[INFO] Tmp directory = some/path/to/my/webapp/target/tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] jetty-9.1.2.v20140210
[INFO] Scanned 1 container path jars, 133 WEB-INF/lib jars, 1 WEB-INF/classes dirs in 1887ms for context o.e.j.m.p.JettyWebAppContext@444942b0{/,file:/some/path/to/my/webapp/,STARTING}{/some/path/to/my/Application-2.3.33+46be96b464dc5b57b2e2e04ce31718a01360e5fb.war}
[INFO] Initializing Spring root WebApplicationContext
INFO:20161021 12:58:27: org.springframework.web.context.ContextLoader org.springframework.web.context.ContextLoader Root WebApplicationContext: initialization started
INFO:20161021 12:58:27: org.springframework.web.context.support.XmlWebApplicationContext org.springframework.context.support.AbstractApplicationContext Refreshing Root WebApplicationContext: startup date [Fri Oct 21 12:58:27 EDT 2016]; root of context hierarchy
INFO:20161021 12:58:27: org.springframework.beans.factory.xml.XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader Loading XML bean definitions from class path resource [spring/app-config.xml]
INFO:20161021 12:58:27: org.springframework.beans.factory.xml.XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader Loading XML bean definitions from class path resource [spring/db-config.xml]
INFO:20161021 12:58:28: org.springframework.beans.factory.support.DefaultListableBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory Overriding bean definition for bean 'endpointLTERepository': replacing [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
[INFO] Started ServerConnector@3a8f9130{HTTP/1.1}{0.0.0.0:8080}
[INFO] Started Jetty Server
/Maven控制台输出结束
我知道 postgresql 嵌入式组件设计用于在同一个单元测试中启动和关闭 Postgres 数据库实例。我正在尝试找到一种使用它的方法,它比最初预期的用例更进一步。本质上,我想要一个 postgresql 嵌入式服务 某种可以从 maven 插件启动然后随后可以用于关闭 postgres 进程。
关于如何create/build这样的服务和/或插件有什么建议吗?
这里的核心问题是能够在插件的两个不同目标之间共享一些状态:一个 start
目标将启动一个进程,然后是一个 stop
目标将杀死它。做到这一点的一个好方法是使用 ContextEnabled
interface that all mojos implement. It provides a getPluginContext()
方法,该方法 returns 一个(原始)地图,您可以在其中存储要在 mojos 之间共享的对象。
通过这种方法,您可以将创建的内容存储在插件的 start
目标中,并在 stop
目标中取回。这里有一个简单的例子来展示这一点,其中一个简单的字符串值在 mojos 之间共享。
Set up a Maven plugin project。这基本上归结为具有以下 POM 的项目,这是 Maven 插件的标准 POM,使用 Java 8 和注释进行配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<packaging>maven-plugin</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
</dependency>
<!-- dependencies to annotations -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
注意 maven-plugin
类型的打包,它向 Maven 声明这是一个插件项目。在这个新项目中,考虑以下 StartMojo
:
@Mojo(name = "start", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST)
public class StartMojo extends AbstractMojo {
@SuppressWarnings("unchecked")
@Override
public void execute() throws MojoExecutionException {
getPluginContext().put("myService", new MyService("foo"));
}
}
这宣布了一个新的 start
mojo which is bound by default to the pre-integration-test
阶段。它检索插件上下文并在其中放入一个新对象。在上面,它是一个名为 MyService
的简单自定义 POJO,它在其构造函数中获取一个值。此对象映射到 "myService"
的键,用作查找。
那么,我们可以有:
@Mojo(name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST)
public class StopMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
MyService service = (MyService) getPluginContext().get("myService");
getLog().info(service.getValue());
}
}
这是在声明一个新的 stop
mojo,它默认绑定到 post-integration-test
阶段。它检索插件上下文,提取键 "myService"
下的对象,最后获取它的值并记录它。
将此 Maven 插件(mvn clean install
)打包并安装到本地存储库后,您可以在示例项目中使用它
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<executions>
<execution>
<id>sample</id>
<goals>
<goal>start</goal>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
如果您在该示例项目上 运行 mvn clean verify
,您最终会在 post-integration-test
阶段在日志中打印 "foo"
。这表明该值已由 start
mojo 正确设置,然后由 stop
mojo 正确检索。
当然,您可以在此地图中存储复杂的对象,而不仅仅是 String
(可能有更简单的解决方案)。值得注意的是,它可能是您要停止的 process
实例的主机。您可以删除 exec-maven-plugin
,创建一个新的 Maven 插件,其中包含您已经在 start
目标中设置嵌入式数据库的代码,将流程实例存储在该目标的插件上下文中,最后在另一个 stop
mojo 中通过从插件上下文中检索它来停止这个过程。
跟进:根据@Tunaki 的建议,我确实创建了自己的 Maven 插件,它使用 postgresql-embedded 的分支到 运行 进程中的 download/installation/initialization一个 9.2 postgreSQL 数据库。
不得不解决一些问题,但这种方法对我来说确实成功了。
这里是 small maven plugin 可以用作 postgresql 嵌入式的 maven 包装器。
我正在尝试为基于 RESTful(服务)Java 的应用程序创建一个全面的集成测试套件,该应用程序在 Tomcat(7.x) 并依赖于 Postgresql (9.x) 实例。此外,如果可能的话,我希望能够 运行 这个套件作为一个独立的进程,完全来自 maven 3.x,通过使用 maven failsafe 插件。这样,测试就可以 运行 跨越 3 个主要平台(Mac OSX、Linux 和 Windows)。
据我所知,我认为实现这一目标的关键是执行以下步骤(按此顺序):
- 在 maven lifecycle 的预集成测试阶段以某种方式启动 postgresql 数据库(和模式设置)的 "embedded" 版本,postgres-db-process 运行在后台运行
- 启动加载我的服务应用程序的 Java 容器:我正在使用 Jetty 9.1.5 插件
- 运行 我在集成测试阶段从 Failsafe 插件进行的(基于 JUnit 的)测试
- 在 Maven 的 post-集成测试阶段 关闭我的 Jetty 容器
- 最后,有一些机制关闭之前启动的(后台)postgres-db-process post-生命周期的集成-测试阶段(kill/clean-up这个过程)
在我当前的实施中,成功完成了步骤 1 - 3。在第 2 步中,它使用 exec-maven-plugin,它调用使用 postgresql-embedded Java component 的 Java class。 摘自 POM.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>Run Postgres DB start/schema setup</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.some.package.test.utils.DbSetup</mainClass>
<arguments>
<argument>setup</argument>
</arguments>
</configuration>
</plugin>
这里是 DBSetup class 的摘录,它使用 postgresql-embedded 来启动 postgresql 实例:
try {
DownloadConfigBuilder downloadConfigBuilder = new DownloadConfigBuilder();
downloadConfigBuilder.defaultsForCommand(Command.Postgres);
downloadConfigBuilder.proxyFactory(new HttpProxyFactory(PROXY_ADDRESS, DEFAULT_PROXY_PORT));
IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
.defaults(Command.Postgres)
.artifactStore(new ArtifactStoreBuilder()
.defaults(Command.Postgres)
.download(downloadConfigBuilder)).build();
PostgresStarter<PostgresExecutable, PostgresProcess> runtime = PostgresStarter.getInstance(runtimeConfig);
final PostgresConfig config = new PostgresConfig(Version.V9_2_4, new AbstractPostgresConfig.Net(
"localhost", 5432
), new AbstractPostgresConfig.Storage(dbName), new AbstractPostgresConfig.Timeout(),
new AbstractPostgresConfig.Credentials(username, password));
config.getAdditionalInitDbParams().addAll(Arrays.asList(
"-E", "UTF-8",
"--locale=en_US.UTF-8",
"--lc-collate=en_US.UTF-8",
"--lc-ctype=en_US.UTF-8"
));
exec = runtime.prepare(config);
process = exec.start();
System.out.println("embedded Postgres started");
Thread.sleep(1200L);
} catch (IOException e) {
System.out.println("Something Went Wrong initializing embedded Postgres: " + e);
e.printStackTrace();
}
catch (InterruptedException e) {
System.out.println("Something Went Wrong Pausing this thread " + e);
e.printStackTrace();
}
请注意,我没有在启动 Postgres 实例的方法中调用 process.stop();
。因此,我目前无法关闭 数据库进程。一旦我退出此 class DbSetup
,所有对该现有进程的引用都将丢失。并且 Postgres 进程永远不会关闭。事实上,jetty 容器似乎也不会关闭,整个 maven 作业都挂了,所以我必须手动杀死它(摘自我的 maven 控制台输出):
[INFO] --- exec-maven-plugin:1.2.1:java (Run Postgres DB start/schema setup) @ BLAHBLAH ---
***START of Postgres DB Setup Process ***
Extract /Users/myUserName/.embedpostgresql/postgresql-9.2.4-1-osx-binaries.zip START
...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................Extract /Users/myUserName/.embedpostgresql/postgresql-9.2.4-1-osx-binaries.zip DONE
INFO:20161021 12:58:00: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[], additionalInitDbParams=[-E, UTF-8, --locale=en_US.UTF-8, --lc-collate=en_US.UTF-8, --lc-ctype=en_US.UTF-8]}
INFO:20161021 12:58:01: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[BLAH], additionalInitDbParams=[]}
INFO:20161021 12:58:04: de.flapdoodle.embed.process.runtime.Executable de.flapdoodle.embed.process.runtime.Executable start AbstractPostgresConfig{storage=Storage{dbDir=/var/folders/8g/69wh31fn7nx3q81phwfdpld00000gn/T/postgresql-embed-66cfc41f-0e16-439f-a24b-6e5b6dbc683d/db-content-3bc4b9cc-dd21-43a7-9058-285767f5c53d, dbName='BLAH', isTmpDir=true}, network=Net{host='localhost', port=5432}, timeout=Timeout{startupTimeout=15000}, credentials=Credentials{BLAH, BLAH}, args=[], additionalInitDbParams=[-E, UTF-8, --locale=en_US.UTF-8, --lc-collate=en_US.UTF-8, --lc-ctype=en_US.UTF-8]}
embedded Postgres started
***END of Postgres DB Setup Process ***
...
[INFO] --- jetty-maven-plugin:9.1.2.v20140210:run-war (start-jetty) @ BLAH ---
[INFO] Configuring Jetty for project: BlahProject
[INFO] Context path = /
[INFO] Tmp directory = some/path/to/my/webapp/target/tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] jetty-9.1.2.v20140210
[INFO] Scanned 1 container path jars, 133 WEB-INF/lib jars, 1 WEB-INF/classes dirs in 1887ms for context o.e.j.m.p.JettyWebAppContext@444942b0{/,file:/some/path/to/my/webapp/,STARTING}{/some/path/to/my/Application-2.3.33+46be96b464dc5b57b2e2e04ce31718a01360e5fb.war}
[INFO] Initializing Spring root WebApplicationContext
INFO:20161021 12:58:27: org.springframework.web.context.ContextLoader org.springframework.web.context.ContextLoader Root WebApplicationContext: initialization started
INFO:20161021 12:58:27: org.springframework.web.context.support.XmlWebApplicationContext org.springframework.context.support.AbstractApplicationContext Refreshing Root WebApplicationContext: startup date [Fri Oct 21 12:58:27 EDT 2016]; root of context hierarchy
INFO:20161021 12:58:27: org.springframework.beans.factory.xml.XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader Loading XML bean definitions from class path resource [spring/app-config.xml]
INFO:20161021 12:58:27: org.springframework.beans.factory.xml.XmlBeanDefinitionReader org.springframework.beans.factory.xml.XmlBeanDefinitionReader Loading XML bean definitions from class path resource [spring/db-config.xml]
INFO:20161021 12:58:28: org.springframework.beans.factory.support.DefaultListableBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory Overriding bean definition for bean 'endpointLTERepository': replacing [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
[INFO] Started ServerConnector@3a8f9130{HTTP/1.1}{0.0.0.0:8080}
[INFO] Started Jetty Server
/Maven控制台输出结束
我知道 postgresql 嵌入式组件设计用于在同一个单元测试中启动和关闭 Postgres 数据库实例。我正在尝试找到一种使用它的方法,它比最初预期的用例更进一步。本质上,我想要一个 postgresql 嵌入式服务 某种可以从 maven 插件启动然后随后可以用于关闭 postgres 进程。
关于如何create/build这样的服务和/或插件有什么建议吗?
这里的核心问题是能够在插件的两个不同目标之间共享一些状态:一个 start
目标将启动一个进程,然后是一个 stop
目标将杀死它。做到这一点的一个好方法是使用 ContextEnabled
interface that all mojos implement. It provides a getPluginContext()
方法,该方法 returns 一个(原始)地图,您可以在其中存储要在 mojos 之间共享的对象。
通过这种方法,您可以将创建的内容存储在插件的 start
目标中,并在 stop
目标中取回。这里有一个简单的例子来展示这一点,其中一个简单的字符串值在 mojos 之间共享。
Set up a Maven plugin project。这基本上归结为具有以下 POM 的项目,这是 Maven 插件的标准 POM,使用 Java 8 和注释进行配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<version>1.0.0</version>
<packaging>maven-plugin</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
</dependency>
<!-- dependencies to annotations -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
注意 maven-plugin
类型的打包,它向 Maven 声明这是一个插件项目。在这个新项目中,考虑以下 StartMojo
:
@Mojo(name = "start", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST)
public class StartMojo extends AbstractMojo {
@SuppressWarnings("unchecked")
@Override
public void execute() throws MojoExecutionException {
getPluginContext().put("myService", new MyService("foo"));
}
}
这宣布了一个新的 start
mojo which is bound by default to the pre-integration-test
阶段。它检索插件上下文并在其中放入一个新对象。在上面,它是一个名为 MyService
的简单自定义 POJO,它在其构造函数中获取一个值。此对象映射到 "myService"
的键,用作查找。
那么,我们可以有:
@Mojo(name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST)
public class StopMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
MyService service = (MyService) getPluginContext().get("myService");
getLog().info(service.getValue());
}
}
这是在声明一个新的 stop
mojo,它默认绑定到 post-integration-test
阶段。它检索插件上下文,提取键 "myService"
下的对象,最后获取它的值并记录它。
将此 Maven 插件(mvn clean install
)打包并安装到本地存储库后,您可以在示例项目中使用它
<plugin>
<groupId>sample.plugin</groupId>
<artifactId>test-maven-plugin</artifactId>
<executions>
<execution>
<id>sample</id>
<goals>
<goal>start</goal>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
如果您在该示例项目上 运行 mvn clean verify
,您最终会在 post-integration-test
阶段在日志中打印 "foo"
。这表明该值已由 start
mojo 正确设置,然后由 stop
mojo 正确检索。
当然,您可以在此地图中存储复杂的对象,而不仅仅是 String
(可能有更简单的解决方案)。值得注意的是,它可能是您要停止的 process
实例的主机。您可以删除 exec-maven-plugin
,创建一个新的 Maven 插件,其中包含您已经在 start
目标中设置嵌入式数据库的代码,将流程实例存储在该目标的插件上下文中,最后在另一个 stop
mojo 中通过从插件上下文中检索它来停止这个过程。
跟进:根据@Tunaki 的建议,我确实创建了自己的 Maven 插件,它使用 postgresql-embedded 的分支到 运行 进程中的 download/installation/initialization一个 9.2 postgreSQL 数据库。
不得不解决一些问题,但这种方法对我来说确实成功了。
这里是 small maven plugin 可以用作 postgresql 嵌入式的 maven 包装器。