How to use the Embedded PostgreSQL Server Java component as a separate service?

二次信任 提交于 2019-12-03 08:52:00

The core problem here, is to be able to share some state between two different goals of a plugin: a start goal that would launch a process, and then a stop goal that would kill it. A good way to do that is to make use of the ContextEnabled interface that all mojos implement. It provides a getPluginContext() method that returns a (raw) map, in which you can store objects to be shared among mojos.

With this approach, you can store something you created in the start goal of a plugin, and get it back in the stop goal. Here's a minimalistic example to show this in action, where a simple String value is shared between mojos.

Set up a Maven plugin project. This basically comes down to having a project with the following POM, which is the standard POM for a Maven plugin, using Java 8 and annotations for configuration:

<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>

Note the packaging of type maven-plugin which declares to Maven that this is a plugin project. In this new project, consider the following 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"));
    }

}

This is declaring a new start mojo which is bound by default to the pre-integration-test phase. It retrieves the plugin context and puts a new object in it. In the above, it is a simple custom POJO called MyService which takes a value in its constructor. This object is mapped to a key of "myService", which serves as look-up.

Then, we can have:

@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());
    }

}

This is declaring a new stop mojo which is bound by default to the post-integration-test phase. It retrieves the plugin context, extracts the object under the key "myService", and finally get its value and logs it.

After packaging and installing this Maven plugin (with mvn clean install) into your local repo, you can use it in a sample project with

<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>

If you run mvn clean verify on that sample project, you'll end up having "foo" printed in your logs, in the post-integration-test phase. This shows that the value was correctly set-up by the start mojo, and then correctly retrieved by the stop mojo.

Of course, you can store complex objects in this map, not just a String (for which there could be more simple solutions). Notably, it could be a host for your process instance that you want to stop. You can get rid of the exec-maven-plugin, create a new Maven plugin containing the code you already have to set up the embedded database in a start goal, store the process instance in the plugin context in this goal, and finally stop this process later in another stop mojo by retrieving it from the plugin context.

Follow-up: Based on @Tunaki suggestion, I did indeed create my own maven plugin that uses a fork of the postgresql-embedded to run an in-process download/installation/initialization of a 9.2 postgreSQL DB.

Had to work out a few kinks, but this approach did succeed for me.

Here is the small maven plugin that can be used as a maven wrapper around postgresql-embedded.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!