All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.axonframework.test.server.AxonServerContainerUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2023. Axon Framework
 *
 * 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 org.axonframework.test.server;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.axonframework.common.Assert;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

/**
 * Utility class for the {@link AxonServerContainer}, used to initialize the cluster.
 *
 * @author Milan Savic
 * @author Sara Pelligrini
 * @since 4.8.0
 */
class AxonServerContainerUtils {

    /**
     * Initialize the cluster of the Axon Server instance located at the given {@code hostname} and {@code port}
     * combination.
     * 

* Note that this constructs the contexts {@code _admin} and {@code default}. * * @param hostname The hostname of the Axon Server instance to initiate the cluster for. * @param port The port of the Axon Server instance to initiate the cluster for. * @throws IOException When there are issues with the HTTP connection to the Axon Server instance at the given * {@code hostname} and {@code port}. */ static void initCluster(String hostname, int port, boolean shouldBeReused) throws IOException { if (shouldBeReused && initialized(hostname, port)) { return; } final URL url = new URL(String.format("http://%s:%d/v1/context/init", hostname, port)); HttpURLConnection connection = null; try { connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.getInputStream().close(); int responseCode = connection.getResponseCode(); Assert.isTrue(202 == responseCode, () -> "The response code [" + responseCode + "] did not match 202."); } finally { if (connection != null) { connection.disconnect(); } } waitForContextsCondition( hostname, port, contexts -> contexts.contains("_admin") && contexts.contains("default") ); } /** * Retrieves all the contexts of the Axon Server instance located at the given {@code hostname} and {@code port} * combination. * * @param hostname The hostname of the Axon Server instance to create the given {@code context} of. * @param port The port of the Axon Server instance to create the given {@code context} of. * @return All the contexts of the Axon Server instances located at the given {@code hostname} and {@code port} * combination. * @throws IOException When there are issues with the HTTP connection to the Axon Server instance at the given * {@code hostname} and {@code port}. */ static List contexts(String hostname, int port) throws IOException { final URL url = new URL(String.format("http://%s:%d/v1/public/context", hostname, port)); HttpURLConnection connection = null; try { connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("Accept", "application/json"); connection.setDoOutput(true); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); Assert.isTrue(200 == responseCode, () -> "The response code [" + responseCode + "] did not match 200."); return contexts(connection); } finally { if (connection != null) { connection.disconnect(); } } } private static List contexts(HttpURLConnection connection) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder output = new StringBuilder(); String outputLine; while ((outputLine = br.readLine()) != null) { output.append(outputLine); } JsonElement jsonElement = JsonParser.parseString(output.toString()); ArrayList contexts = new ArrayList<>(); for (JsonElement element : jsonElement.getAsJsonArray()) { String context = element.getAsJsonObject() .get("context") .getAsString(); contexts.add(context); } return contexts; } private static void waitForContextsCondition(String hostname, int port, Predicate> condition) { ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); CountDownLatch latch = new CountDownLatch(1); try { scheduler.submit(() -> checkContextsCondition(hostname, port, condition, latch, scheduler)) .get(); if (!latch.await(60, TimeUnit.SECONDS)) { throw new RuntimeException("Condition on contexts has not been met!"); } } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } finally { scheduler.shutdown(); } } private static void checkContextsCondition(String hostname, int port, Predicate> condition, CountDownLatch latch, ScheduledExecutorService scheduler) { try { if (condition.test(contexts(hostname, port))) { latch.countDown(); } else { scheduler.schedule( () -> checkContextsCondition(hostname, port, condition, latch, scheduler), 10, TimeUnit.MILLISECONDS ); } } catch (IOException e) { throw new RuntimeException(e); } } private static boolean initialized(String hostname, int port) throws IOException { try { List cont = contexts(hostname, port); return cont.contains("_admin") && cont.contains("default"); } catch (IllegalArgumentException e) { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy