自定义Quarkus开发服务

huangapple go评论82阅读模式
英文:

Custom dev-Service for Quarkus

问题

我正在使用Quarkus作为框架创建一个Web服务,该服务使用另一个Web服务。我认为使用与Quarkus用于数据库等的相同的开发服务机制来启动包含该其他服务(或其模拟服务)的容器会很不错。

我已经成功地在JUnit测试中实现了一个QuarkusTestResourceLifecycleManager类来实现这一点:

        // 创建镜像
        ImageFromDockerfile image = new ImageFromDockerfile()...
        // 创建容器
        GenericContainer<?> container = new GenericContainer<>(image)...
        // 启动容器
        container.start();

现在我想在开发模式下使用相同的容器。最好是作为开发服务,这也显示在开发UI中。

这方面的最佳实践是什么?是否有关于API的文档,我找不到吗?

英文:

I am creating a web service using Quarkus as framework, which uses another web service. I thought it would be nice to use the same dev service mechanism, which quarkus uses for databasesm, etc. to start up a container containing this other service (or a mock service of it).

I was able to achieve this for JUnit testing with implementing a class of QuarkusTestResourceLifecycleManager:

        // Create the Image
        ImageFromDockerfile image = new ImageFromDockerfile()...
        // Create the Container
        GenericContainer&lt;?&gt; container = new GenericContainer&lt;&gt;(image)...
        // Start the Container
        container.start();

Now I would like to use the same container in dev mode. Ideally as dev service, which is also shown in the devUI.

What is the best practice for that? Is there any documentation on the API, which I did not find?

答案1

得分: 1

以下是翻译好的部分:

  1. Quarkus 有一些关于编写扩展的资源:

  2. 要创建一个扩展,您可以运行类似以下的命令:

    mvn io.quarkus.platform:quarkus-maven-plugin:3.2.0.Final:create-extension -N \
        -DgroupId=org.acme \ 
        -DextensionId=other-web-service
    
  3. 一旦您有了扩展的框架,添加开发服务的代码非常紧凑。在处理器中,您需要添加一个生成类型为 'dev services' 的构建项的构建步骤。构建项 有点像扩展的 API,您可以通过构造并返回正确类型的构建项来实现大多数所需的功能。

@BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class)
public DevServicesResultBuildItem createContainer(LaunchModeBuildItem launchMode) {

    DockerImageName dockerImageName = DockerImageName.parse("namespace/other-web-service");
    
    // 您可能想在这里使用 Quarkus 配置来自定义容器
    OtherWebServiceContainer container = new OtherWebServiceContainer()
            .withEnv("whatever", "true")
            .withEnv("otherenv", "something")
            
    container.start();

    Map<String, String> props = Map.of("mynew.url",
            "https://" + container.getHost() + ":" + container.getPort());
    return new DevServicesResultBuildItem.RunningDevService(FEATURE, container.getContainerId(),
            container::close, props)
            .toBuildItem();
}

private static class OtherWebServiceContainer extends GenericContainer<OtherWebServiceContainer> {
    static final int PORT = 25565;

    public OtherWebServiceContainer(DockerImageName image) {
        super(image);
    }

    @Override
    protected void configure() {
        withNetwork(Network.SHARED);
        addExposedPorts(PORT);
        // 告诉开发服务容器何时准备就绪
        waitingFor(Wait.forLogMessage(".*Listening on http://0.0.0.0:9292.*", 1)); 
    }

    public Integer getPort() {
        return this.getMappedPort(PORT);
    }
}

如果您遇到困难,浏览Quarkus 代码库以查看如何创建开发服务的示例应该会给您一些想法。

英文:

For this, you'd need to write an extension for the other web service. Quarkus have a few resources about writing extensions:

To scaffold an extension, you'd run something like

mvn io.quarkus.platform:quarkus-maven-plugin:3.2.0.Final:create-extension -N \
    -DgroupId=org.acme \ 
    -DextensionId=other-web-service

Once you have your skeleton extension, the code to add a dev service is pretty compact. In the processor, you need to add a build step producing a build item of type 'dev services'. The build items are a bit like the API for extensions, and you can achieve most things you want just by constructing and returning a build item of the right kind.

    @BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class)
    public DevServicesResultBuildItem createContainer(LaunchModeBuildItem launchMode) {

        DockerImageName dockerImageName = DockerImageName.parse(&quot;namespace/other-web-service&quot;);
        
        // You might want to use Quarkus config here to customise the container
        OtherWebServiceContainer container = new OtherWebServiceContainer()
                .withEnv(&quot;whatever&quot;, &quot;true&quot;)
                .withEnv(&quot;otherenv&quot;, &quot;something&quot;)
                
        container.start();

        Map&lt;String, String&gt; props = Map.of(&quot;mynew.url&quot;,
                &quot;https://&quot; + container.getHost() + &quot;:&quot; + container.getPort());
        return new DevServicesResultBuildItem.RunningDevService(FEATURE, container.getContainerId(),
                container::close, props)
                .toBuildItem();
    }

    private static class OtherWebServiceContainer extends GenericContainer&lt;OtherWebServiceContainer&gt; {
        static final int PORT = 25565;

        public OtherWebServiceContainer(DockerImageName image) {
            super(image);
        }

        @Override
        protected void configure() {
            withNetwork(Network.SHARED);
            addExposedPorts(PORT);
            // Tell the dev service how to know the container is ready
            waitingFor(Wait.forLogMessage(&quot;.*Listening on http://0.0.0.0:9292.*&quot;, 1)); 
        }

        public Integer getPort() {
            return this.getMappedPort(PORT);
        }
    }

If you get stuck, looking through the Quarkus codebase for examples of how dev services are created should give you ideas.

huangapple
  • 本文由 发表于 2023年7月11日 13:44:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定