diff --git a/CHANGELOG.md b/CHANGELOG.md index d4ed580..5d8014c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Deprecated ### Security +[1.2.5] - 2024-05-14 +### Changed +- Aggiornamento del file README.md sezione Scenari di Test con JMeter e Taurus +- Aggiornamento della gestione degli Event Handler attraverso la configurazione di Quarkus +- Adeguamento file JMX `scenario_2.jmx` + +### Fixed +- Risoluzione issue di SonarCloud + [1.2.4] - 2024-05-13 ### Added - Aggiunto altro unit test per la pubblicazione di messaggi fake diff --git a/README.md b/README.md index 42bcef4..cd809c0 100644 --- a/README.md +++ b/README.md @@ -274,7 +274,7 @@ Puoi eseguire l'applicazione in modalità sviluppo che abilita il live coding ut ``` Console 6 - Esecuzione dell'applicazione in modalità sviluppo -> **_NOTE:_** Quarkus ora include una UI di sviluppo, disponibile solo in modalità sviluppo all'indirizzo http://localhost:8080/q/dev/. +> **_NOTE:_** Quarkus ora include una UI di sviluppo, disponibile solo in modalità sviluppo all'indirizzo http://localhost:8080/q/dev/. ![Quarkus Dev UI](src/doc/resources/images/quarkus_dev_ui_home_page.jpg) @@ -383,7 +383,7 @@ eseguito in locale, per cui abbiate cura di avere l'applicazione Quarkus in esec I Thread Group in questo caso sono stati configurati per simulare 100 utenti virtuali che inviano 300 richieste al servizio REST `api/rest/echo` esposto dall'applicazione Quarkus con un periodo di ramp-up di 0.5 secondi. -> **_NOTA:_** I dati mostrati a seguire fanno riferimento all'esecuzione del Test Plan sull'ambiente Developer +> **_NOTA:_** I dati mostrati a seguire fanno riferimento all'esecuzione del Test Plan sull'ambiente Developer > Sandbox di Red Hat OpenShift, con attivi tre pod dell'applicazione Quarkus, un pod per il servizio MongoDB e un pod > per il servizio AMQP (Apache ActiveMQ Artemis). @@ -425,6 +425,69 @@ potete vedere la struttura aprendolo con JMeter. A seguire è mostrata la strutt Figura 8 - Configurazione del Test Plan di JMeter (scenario 2 `src/test/jmeter/scenario_2.jmx`) +I thread group sono stati configurati con lo stesso principio del primo scenario di Load Testing, di conseguenza sono +stati creati per versione di protocollo HTTP (HTTPS/1.1, HTTP/2 over TLS e compressed); per ognuno di essi è stato +creato un flusso di richieste verso i servizi JAX-RS dell'entità ORM `Owner` e `Horse` (introdotte dalla versione +[1.2.0](https://github.com/amusarra/eventbus-logging-filter-jaxrs/releases/tag/v1.2.0) del progetto). + +Per questo scenario, attraverso l'elemento di configurazione [HTTP Header Manager](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Header_Manager), sono stati configurati un set di header HTTP custom e che +riguardano nello specifico delle informazioni su JMeter; questi sono: +1. X-TestCaseId: un identificativo univoco del test case +2. X-TestPlanName: il nome del test plan +3. X-TestThreadGroupName: il nome del thread group +4. X-TestThreadNumber: il numero del thread + +Queste informazioni possono essere utili per tracciare le richieste HTTP inviate da JMeter e per identificare il test. +A seguire un esempio di una richiesta eseguita da JMeter e tracciata su MongoDB dove sono evidenti gli header HTTP custom. + +```bson +{ + "_id" : ObjectId("66425a820d65f7240e2ba113"), + "X-Correlation-ID" : "bc187f1f-9c6c-499b-9d13-0b87b31d2abb", + "remote-ip-address" : "127.0.0.1", + "headers" : { + "Accept" : [ + "*/*" + ], + "X-TestThreadGroupName" : [ + "HTTPS/1.1" + ], + "Connection" : [ + "keep-alive" + ], + "User-Agent" : [ + "Java/21.0.2" + ], + "X-TestPlanName" : [ + "modified_scenario_2.jmx" + ], + "Host" : [ + "127.0.0.1:8443" + ], + "X-TestCaseId" : [ + "005044d0-9848-4f22-8e50-02fa395a5ede" + ], + "Content-Length" : [ + "296" + ], + "Content-Type" : [ + "application/json;charset=UTF-8" + ], + "X-TestThreadNumber" : [ + "1" + ] + }, + "body" : "{\r\n \"name\": \"Crimson Comet-updated\",\r\n \"sex\": \"F\",\r\n \"coat\": \"chestnut\",\r\n \"breed\": \"Appaloosa\",\r\n \"dateOfBirth\": \"2004-01-19\",\r\n \"registrationNumber\": \"0FOTDW12MI531U\",\r\n \"microchipNumber\": \"C782CF2I1IN\",\r\n \"passportNumber\": \"39K4CK1I3ZDU4\",\r\n \"height\": 134,\r\n \"owners\": [{\"id\": 3}]\r\n}", + "uri-info" : "https://127.0.0.1:8443/api/rest/repository/horse/v1/6", + "local-date-time-in" : "2024-05-13T20:22:58.622629", + "method" : "PUT", + "media-type" : "application/json", + "acceptable-language" : "[]", + "acceptable-media-types" : "[*/*]" +} +``` +Log 3 - Esempio di richiesta HTTP tracciata su MongoDB + È possibile eseguire questo scenario sempre con Taurus utilizzando comando `bzt` come mostrato in precedenza. A seguire è riportato il comando per eseguire lo scenario di Load Testing con Taurus. @@ -446,8 +509,6 @@ Dalla versione [1.2.4](https://github.com/amusarra/eventbus-logging-filter-jaxrs in esecuzione quando questa è avviata utilizzando il docker-compose. Questo è possibile grazie alla configurazione mostrata a seguire e in particolare i parametri `JAVA_OPTS` che abilitano la JMX. -```shell script - ```yaml logging-filter: # Use the following image if you want to use the pre-built image from Docker Hub: diff --git a/pom.xml b/pom.xml index 7afd23e..5540abe 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 it.dontesta.eventbus eventbus-logging-filter-jaxrs - 1.2.4 + 1.2.5 eventbus-logging-filter-jaxrs Event Bus Logging Filter JAX-RS https://amusarra.github.io/eventbus-logging-filter-jaxrs-docs diff --git a/src/doc/resources/images/jmeter_configurazione_piano_test_scenario_2.jpg b/src/doc/resources/images/jmeter_configurazione_piano_test_scenario_2.jpg index 9c5510e..2702d1a 100644 Binary files a/src/doc/resources/images/jmeter_configurazione_piano_test_scenario_2.jpg and b/src/doc/resources/images/jmeter_configurazione_piano_test_scenario_2.jpg differ diff --git a/src/main/java/it/dontesta/eventbus/application/configuration/EventHandlerAddress.java b/src/main/java/it/dontesta/eventbus/application/configuration/EventHandlerAddress.java new file mode 100644 index 0000000..c82675d --- /dev/null +++ b/src/main/java/it/dontesta/eventbus/application/configuration/EventHandlerAddress.java @@ -0,0 +1,78 @@ +package it.dontesta.eventbus.application.configuration; + +import java.util.List; + +/** + * Questa classe rappresenta l'indirizzo dell'event handler. + * + *

Questo componente è usato per definire l'indirizzo dell'event handler e se è abilitato o meno + * e usato dal converter {@code EventHandlerAddressConverter} per convertire la stringa di + * configurazione in un oggetto {@code EventHandlerAddress}. + * + * @see it.dontesta.eventbus.application.configuration.converter.EventHandlerAddressConverter + */ +public class EventHandlerAddress { + + private String address; + + private boolean enabled; + + /** + * Costruttore di default. + */ + public EventHandlerAddress(String address, boolean enabled) { + this.address = address; + this.enabled = enabled; + } + + /** + * Restituisce l'indirizzo dell'event handler. + * + * @return l'indirizzo dell'event handler + */ + public String getAddress() { + return address; + } + + /** + * Imposta l'indirizzo dell'event handler. + * + * @param address l'indirizzo dell'event handler + */ + public void setAddress(String address) { + this.address = address; + } + + /** + * Restituisce se l'event handler è abilitato o meno. + * + * @return true se l'event handler è abilitato, false altrimenti + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Imposta se l'event handler è abilitato o meno. + * + * @param enabled true se l'event handler è abilitato, false altrimenti + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /** + * Verifica se l'indirizzo dell'event handler esiste e se è abilitato. + * + * @param eventHandlerAddresses la lista degli indirizzi degli event handler + * @param address l'indirizzo dell'event handler + * @return true se l'indirizzo dell'event handler esiste e se è abilitato, false altrimenti + */ + public static boolean isAddressAndExistsEnabled(List eventHandlerAddresses, + String address) { + return eventHandlerAddresses.stream() + .anyMatch(eventHandlerAddress -> + eventHandlerAddress.getAddress().equals(address) && + eventHandlerAddress.isEnabled()); + } +} diff --git a/src/main/java/it/dontesta/eventbus/application/configuration/converter/EventHandlerAddressConverter.java b/src/main/java/it/dontesta/eventbus/application/configuration/converter/EventHandlerAddressConverter.java new file mode 100644 index 0000000..9087d57 --- /dev/null +++ b/src/main/java/it/dontesta/eventbus/application/configuration/converter/EventHandlerAddressConverter.java @@ -0,0 +1,40 @@ +package it.dontesta.eventbus.application.configuration.converter; + +import it.dontesta.eventbus.application.configuration.EventHandlerAddress; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.eclipse.microprofile.config.spi.Converter; + +/** + * Questa classe implementa l'interfaccia {@code Converter} per convertire una stringa in un oggetto + * {@code EventHandlerAddress}. + * + *

Questo converter è utilizzato in modo specifico per convertire le proprietà di configurazione + * relative agli indirizzi degli event handler. La proprietà di configurazione si chiama + * {@code app.eventbus.consumer.event.handler.addresses[i]} dove i è un numero intero che + * rappresenta l'indice dell'indirizzo dell'event handler. + * + *

Il formato della stringa è il seguente: {@code address=address,enabled=enabled} dove address è + * l'indirizzo dell'event handler e enabled è un flag booleano che indica se l'event handler è + * abilitato o meno. + */ +public class EventHandlerAddressConverter implements Converter { + + @Override + public EventHandlerAddress convert(String value) { + // Definisci il pattern per estrarre i valori di address ed enabled dalle properties + Pattern pattern = Pattern.compile("address=(.*),enabled=(.*)"); + Matcher matcher = pattern.matcher(value.trim()); + + // Itera su tutte le occorrenze del pattern nella stringa value + while (matcher.find()) { + String address = matcher.group(1); + boolean enabled = Boolean.parseBoolean(matcher.group(2)); + if (address != null && !address.isEmpty()) { + return (new EventHandlerAddress(address, enabled)); + } + } + throw new IllegalArgumentException( + "Failed to parse Event Handler Address {%s}".formatted(value)); + } +} \ No newline at end of file diff --git a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/Dispatcher.java b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/Dispatcher.java index 55252fd..7c69aef 100644 --- a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/Dispatcher.java +++ b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/Dispatcher.java @@ -8,6 +8,7 @@ import io.vertx.mutiny.core.eventbus.EventBus; import io.vertx.mutiny.core.eventbus.Message; import io.vertx.mutiny.core.eventbus.MessageConsumer; +import it.dontesta.eventbus.application.configuration.EventHandlerAddress; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; @@ -20,7 +21,9 @@ * gli eventi ricevuti dall'event bus tramite il metodo {@code handleEvent}. * *

Questo componente è responsabile di inviare gli eventi ricevuti da un consumer a uno o più - * consumer target specificati nell'header {@TARGET_VIRTUAL_ADDRESSES} del messaggio. + * consumer target che sono stati abilitati da configurazione + * {@code app.eventbus.consumer.event.handler.addresses}. Questi consumer target sono i cosiddetti + * event handler. * *

La registrazione avviene all'avvio dell'applicazione tramite l'annotazione {@code @Observes} * e il metodo {@code onStart}. @@ -29,7 +32,7 @@ * di configurazione {@code app.eventbus.consumer.dispatcher.address} che viene iniettato tramite * l'annotazione {@code @ConfigProperty} * - *

In questo caso il dispatcher invia l'evento ricevuto a uno o più consumer target specificati + *

In questo caso il dispatcher invia l'evento ricevuto a uno o più consumer target configurati * attendendo una risposta da ciascuno di essi scrivendo il risultato sul log. */ @ApplicationScoped @@ -43,14 +46,15 @@ public class Dispatcher { @ConfigProperty(name = "app.eventbus.consumer.dispatcher.address") String dispatcherVirtualAddress; + @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") + List eventHandlerVirtualAddresses; + MessageConsumer consumer; public static final String SOURCE_VIRTUAL_ADDRESS = "source-virtual-address"; public static final String SOURCE_COMPONENT = "source-component"; - public static final String TARGET_VIRTUAL_ADDRESSES = "target-virtual-addresses"; - void onStart(@Observes StartupEvent ev) { log.debugf( "Registering the Dispatcher to the event bus for the event handler at addresses: {%s}", @@ -78,16 +82,24 @@ public void handleEvent(Message message) { // Leggere gli header dalle DeliveryOptions String sourceVirtualAddress = message.headers().get(SOURCE_VIRTUAL_ADDRESS); String sourceComponent = message.headers().get(SOURCE_COMPONENT); - List targetVirtualAddressesList = - List.of(message.headers().get(TARGET_VIRTUAL_ADDRESSES).split(",")); + + // Filtra gli indirizzi degli event handler abilitati + List enabledEventHandlerAddresses = eventHandlerVirtualAddresses.stream() + .filter(EventHandlerAddress::isEnabled) + .toList(); + + // Estrai la lista degli indirizzi virtuali di destinazione + List targetVirtualAddressesList = enabledEventHandlerAddresses.stream() + .map(EventHandlerAddress::getAddress) + .toList(); log.debugf( - new StringBuilder().append( - "Received event message from source virtual address: %s and source component: %s ") - .append("for the target virtual addresses: %s").toString(), - sourceVirtualAddress, sourceComponent, message.headers().get(TARGET_VIRTUAL_ADDRESSES)); + "Received event message from source virtual address: %s and source component: %s " + + "for the target virtual addresses: %s", + sourceVirtualAddress, sourceComponent, targetVirtualAddressesList); // Invia l'evento a tutti i target virtual addresses + // che sono stati abilitati da configurazione app.eventbus.consumer.event.handler.addresses targetVirtualAddressesList.forEach(targetVirtualAddress -> { // Creare le opzioni di consegna desiderate diff --git a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/nosql/MongoDbEventHandler.java b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/nosql/MongoDbEventHandler.java index 477dbfe..8a9df75 100644 --- a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/nosql/MongoDbEventHandler.java +++ b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/nosql/MongoDbEventHandler.java @@ -1,5 +1,7 @@ package it.dontesta.eventbus.consumers.events.handlers.nosql; +import static it.dontesta.eventbus.application.configuration.EventHandlerAddress.*; + import io.quarkus.mongodb.reactive.ReactiveMongoClient; import io.quarkus.mongodb.reactive.ReactiveMongoCollection; import io.quarkus.runtime.ShutdownEvent; @@ -8,11 +10,13 @@ import io.vertx.mutiny.core.eventbus.EventBus; import io.vertx.mutiny.core.eventbus.Message; import io.vertx.mutiny.core.eventbus.MessageConsumer; +import it.dontesta.eventbus.application.configuration.EventHandlerAddress; import it.dontesta.eventbus.consumers.http.HttpRequestConsumer; import it.dontesta.eventbus.consumers.http.HttpResponseConsumer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; +import java.util.List; import org.bson.Document; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; @@ -27,10 +31,11 @@ * *

La registrazione avviene all'avvio dell'applicazione tramite l'annotazione {@code @Observes} * e il metodo {@code onStart}, mentre la de-registrazione avviene all'arresto dell'applicazione - * attraverso il metodo {@code onStop}. + * attraverso il metodo {@code onStop}. La registrazione avviene solo se l'indirizzo dell'event handler + * è abilitato. * *

L'indicazione dell'indirizzo virtuale dell'evento per l'Event Handler è definita nel parametro - * di configurazione {@code app.eventbus.consumer.event.handler.addresses[1]} che viene iniettato + * di configurazione {@code app.eventbus.consumer.event.handler.addresses} che viene iniettato * tramite l'annotazione {@code @ConfigProperty} * * @author Antonio Musarra @@ -47,8 +52,8 @@ public class MongoDbEventHandler { @Inject ReactiveMongoClient mongoClient; - @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses[1]") - String mongoDbEventHandlerVirtualAddress; + @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") + List eventHandlerAddresses; @ConfigProperty(name = "app.eventbus.consumer.event.handler.nosql.mongodb.database.name", defaultValue = "audit") @@ -62,13 +67,20 @@ public class MongoDbEventHandler { public static final String SOURCE_COMPONENT = "source-component"; + public static final String SOURCE_VIRTUAL_ADDRESS_NOSQL = "nosql-trace"; + void onStart(@Observes StartupEvent ev) { - log.debugf( - "Registering the MongoDB event handler at addresses: {%s}", - mongoDbEventHandlerVirtualAddress); - consumer = eventBus.consumer(mongoDbEventHandlerVirtualAddress); - consumer.handler(this::handleEvent); + if (isAddressAndExistsEnabled( + eventHandlerAddresses, SOURCE_VIRTUAL_ADDRESS_NOSQL)) { + log.debugf( + "Registering the MongoDB event handler at addresses: {%s}", + SOURCE_VIRTUAL_ADDRESS_NOSQL); + + consumer = eventBus.consumer(SOURCE_VIRTUAL_ADDRESS_NOSQL); + consumer.handler(this::handleEvent); + } + } void onStop(@Observes ShutdownEvent ev) { @@ -76,7 +88,7 @@ void onStop(@Observes ShutdownEvent ev) { consumer.unregisterAndAwait(); log.debugf( "Unregistering the MongoDB event handler at addresses: {%s}", - mongoDbEventHandlerVirtualAddress); + SOURCE_VIRTUAL_ADDRESS_NOSQL); } } diff --git a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/queue/AmqpEventHandler.java b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/queue/AmqpEventHandler.java index b34500f..45b48c7 100644 --- a/src/main/java/it/dontesta/eventbus/consumers/events/handlers/queue/AmqpEventHandler.java +++ b/src/main/java/it/dontesta/eventbus/consumers/events/handlers/queue/AmqpEventHandler.java @@ -1,16 +1,20 @@ package it.dontesta.eventbus.consumers.events.handlers.queue; +import static it.dontesta.eventbus.application.configuration.EventHandlerAddress.isAddressAndExistsEnabled; + import io.quarkus.runtime.ShutdownEvent; import io.quarkus.runtime.StartupEvent; import io.vertx.core.json.JsonObject; import io.vertx.mutiny.core.eventbus.EventBus; import io.vertx.mutiny.core.eventbus.Message; import io.vertx.mutiny.core.eventbus.MessageConsumer; +import it.dontesta.eventbus.application.configuration.EventHandlerAddress; import it.dontesta.eventbus.consumers.http.HttpRequestConsumer; import it.dontesta.eventbus.consumers.http.HttpResponseConsumer; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; +import java.util.List; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; @@ -26,10 +30,11 @@ * *

La registrazione avviene all'avvio dell'applicazione tramite l'annotazione {@code @Observes} * e il metodo {@code onStart}, mentre la de-registrazione avviene all'arresto dell'applicazione - * attraverso il metodo {@code onStop}. + * attraverso il metodo {@code onStop}. La registrazione avviene solo se l'indirizzo dell'event handler + * è abilitato. * *

L'indicazione dell'indirizzo virtuale dell'evento per l'Event Handler è definita nel parametro - * di configurazione {@code app.eventbus.consumer.event.handler.addresses[2]} che viene iniettato + * di configurazione {@code app.eventbus.consumer.event.handler.addresses} che viene iniettato * tramite l'annotazione {@code @ConfigProperty} */ @ApplicationScoped @@ -47,26 +52,32 @@ public class AmqpEventHandler { @Inject Logger log; - @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses[2]") - String amqpEventHandlerVirtualAddress; + @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") + List eventHandlerAddresses; MessageConsumer consumer; public static final String SOURCE_COMPONENT = "source-component"; + public static final String SOURCE_VIRTUAL_ADDRESS_QUEUE = "queue-trace"; + void onStart(@Observes StartupEvent ev) { - log.debugf("Registering the AMQP event handler at addresses: {%s}", - amqpEventHandlerVirtualAddress); - consumer = eventBus.consumer(amqpEventHandlerVirtualAddress); - consumer.handler(this::handleEvent); + if (isAddressAndExistsEnabled( + eventHandlerAddresses, SOURCE_VIRTUAL_ADDRESS_QUEUE)) { + log.debugf("Registering the AMQP event handler at addresses: {%s}", + SOURCE_VIRTUAL_ADDRESS_QUEUE); + + consumer = eventBus.consumer(SOURCE_VIRTUAL_ADDRESS_QUEUE); + consumer.handler(this::handleEvent); + } } void onStop(@Observes ShutdownEvent ev) { if (consumer != null) { consumer.unregisterAndAwait(); log.debugf("Unregistering the AMQP event handler at addresses: {%s}", - amqpEventHandlerVirtualAddress); + SOURCE_VIRTUAL_ADDRESS_QUEUE); } } diff --git a/src/main/java/it/dontesta/eventbus/consumers/http/HttpRequestConsumer.java b/src/main/java/it/dontesta/eventbus/consumers/http/HttpRequestConsumer.java index 3fd1850..b3f5803 100644 --- a/src/main/java/it/dontesta/eventbus/consumers/http/HttpRequestConsumer.java +++ b/src/main/java/it/dontesta/eventbus/consumers/http/HttpRequestConsumer.java @@ -10,7 +10,6 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; -import java.util.List; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; @@ -41,17 +40,12 @@ public class HttpRequestConsumer { @ConfigProperty(name = "app.eventbus.consumer.dispatcher.address") String dispatcherVirtualAddress; - @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") - List eventHandlerVirtualAddresses; - MessageConsumer consumer; public static final String SOURCE_VIRTUAL_ADDRESS = "source-virtual-address"; public static final String SOURCE_COMPONENT = "source-component"; - public static final String TARGET_VIRTUAL_ADDRESSES = "target-virtual-addresses"; - void onStart(@Observes StartupEvent ev) { log.debugf( "Registering the consumers to the event bus for HTTP request at addresses: {%s}", @@ -81,7 +75,6 @@ void onStop(@Observes ShutdownEvent ev) { public void handleEvent(Message message) { // Creare le opzioni di consegna desiderate DeliveryOptions options = new DeliveryOptions() - .addHeader(TARGET_VIRTUAL_ADDRESSES, String.join(",", eventHandlerVirtualAddresses)) .addHeader(SOURCE_VIRTUAL_ADDRESS, httpRequestVirtualAddress) .addHeader(SOURCE_COMPONENT, HttpRequestConsumer.class.getName()); diff --git a/src/main/java/it/dontesta/eventbus/consumers/http/HttpResponseConsumer.java b/src/main/java/it/dontesta/eventbus/consumers/http/HttpResponseConsumer.java index 942cea4..cab7087 100644 --- a/src/main/java/it/dontesta/eventbus/consumers/http/HttpResponseConsumer.java +++ b/src/main/java/it/dontesta/eventbus/consumers/http/HttpResponseConsumer.java @@ -10,7 +10,6 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; -import java.util.List; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.jboss.logging.Logger; @@ -42,17 +41,12 @@ public class HttpResponseConsumer { @ConfigProperty(name = "app.eventbus.consumer.dispatcher.address") String dispatcherVirtualAddress; - @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") - List eventHandlerVirtualAddresses; - MessageConsumer consumer; public static final String SOURCE_VIRTUAL_ADDRESS = "source-virtual-address"; public static final String SOURCE_COMPONENT = "source-component"; - public static final String TARGET_VIRTUAL_ADDRESSES = "target-virtual-addresses"; - void onStart(@Observes StartupEvent ev) { log.debugf( "Registering the consumers to the event bus for HTTP response at addresses: {%s}", @@ -82,7 +76,6 @@ void onStop(@Observes ShutdownEvent ev) { public void handleEvent(Message message) { // Creare le opzioni di consegna desiderate DeliveryOptions options = new DeliveryOptions() - .addHeader(TARGET_VIRTUAL_ADDRESSES, String.join(",", eventHandlerVirtualAddresses)) .addHeader(SOURCE_VIRTUAL_ADDRESS, httpResponseVirtualAddress) .addHeader(SOURCE_COMPONENT, HttpResponseConsumer.class.getName()); diff --git a/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter b/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter new file mode 100644 index 0000000..b1387d2 --- /dev/null +++ b/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.Converter @@ -0,0 +1 @@ +it.dontesta.eventbus.application.configuration.converter.EventHandlerAddressConverter \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 32fcaf6..267b0fd 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -136,9 +136,9 @@ app.eventbus.consumer.http.request.address=http-request app.eventbus.consumer.http.response.address=http-response # Define the Event Bus virtual address for event handler SQL, NoSQL and Queue -app.eventbus.consumer.event.handler.addresses[0]=sql-trace -app.eventbus.consumer.event.handler.addresses[1]=nosql-trace -app.eventbus.consumer.event.handler.addresses[2]=queue-trace +app.eventbus.consumer.event.handler.addresses[0]=address=sql-trace,enabled=false +app.eventbus.consumer.event.handler.addresses[1]=address=nosql-trace,enabled=true +app.eventbus.consumer.event.handler.addresses[2]=address=queue-trace,enabled=true # Define the Event Bus virtual address for the Dispatcher app.eventbus.consumer.dispatcher.address=dispatcher-event diff --git a/src/test/java/it/dontesta/eventbus/application/configuration/ApplicationConfigurationTest.java b/src/test/java/it/dontesta/eventbus/application/configuration/ApplicationConfigurationTest.java new file mode 100644 index 0000000..b393561 --- /dev/null +++ b/src/test/java/it/dontesta/eventbus/application/configuration/ApplicationConfigurationTest.java @@ -0,0 +1,88 @@ +package it.dontesta.eventbus.application.configuration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import io.quarkus.test.junit.QuarkusTest; +import it.dontesta.eventbus.application.configuration.converter.EventHandlerAddressConverter; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@QuarkusTest +class ApplicationConfigurationTest { + + @ConfigProperty(name = "app.eventbus.consumer.event.handler.addresses") + List eventHandlerVirtualAddresses; + + @BeforeEach + void setUp() { + converter = new EventHandlerAddressConverter(); + eventHandlerAddress = new EventHandlerAddress("testAddress", true); + + eventHandlerAddresses = new ArrayList<>(); + eventHandlerAddresses.add(new EventHandlerAddress("testAddress1", true)); + eventHandlerAddresses.add(new EventHandlerAddress("testAddress2", false)); + eventHandlerAddresses.add(new EventHandlerAddress("testAddress3", true)); + + } + + @Test + void testConvertWithInvalidInput() { + String input = "invalidInput"; + assertThrows(IllegalArgumentException.class, () -> converter.convert(input)); + } + + @Test + void testEventBusConsumerEventHandlerAddresses() { + Assertions.assertNotNull(eventHandlerVirtualAddresses); + Assertions.assertFalse(eventHandlerVirtualAddresses.isEmpty()); + Assertions.assertTrue(eventHandlerVirtualAddresses.size() >= 2); + } + + @Test + void getAddress() { + assertEquals("testAddress", eventHandlerAddress.getAddress()); + } + + @Test + void setAddress() { + eventHandlerAddress.setAddress("newAddress"); + assertEquals("newAddress", eventHandlerAddress.getAddress()); + } + + @Test + void isEnabled() { + assertTrue(eventHandlerAddress.isEnabled()); + } + + @Test + void setEnabled() { + eventHandlerAddress.setEnabled(false); + assertFalse(eventHandlerAddress.isEnabled()); + } + + @Test + void testIsAddressAndExistsEnabled() { + // Test when address exists and is enabled + assertTrue(EventHandlerAddress.isAddressAndExistsEnabled(eventHandlerAddresses, "testAddress1")); + + // Test when address exists but is not enabled + assertFalse(EventHandlerAddress.isAddressAndExistsEnabled(eventHandlerAddresses, "testAddress2")); + + // Test when address does not exist + assertFalse(EventHandlerAddress.isAddressAndExistsEnabled(eventHandlerAddresses, "nonExistingAddress")); + } + + + private List eventHandlerAddresses; + + private EventHandlerAddress eventHandlerAddress; + + private EventHandlerAddressConverter converter; +} diff --git a/src/test/jmeter/scenario_2.jmx b/src/test/jmeter/scenario_2.jmx index f25ea77..6806523 100644 --- a/src/test/jmeter/scenario_2.jmx +++ b/src/test/jmeter/scenario_2.jmx @@ -24,7 +24,7 @@ numberOfThreads = - ${__P(numberOfThreads,6)} + ${__P(numberOfThreads,1)} rampUpPeriod @@ -34,7 +34,7 @@ loopCount = - ${__P(loopCount,10)} + ${__P(loopCount,1)} @@ -63,6 +63,22 @@ Connect to 5s Content-Type application/json;charset=UTF-8 + + X-TestCaseId + ${__UUID} + + + X-TestPlanName + ${__TestPlanName} + + + X-TestThreadGroupName + ${__threadGroupName} + + + X-TestThreadNumber + ${__threadNum} + @@ -90,7 +106,7 @@ Connect to 5s true shareMode.all false - name,sex,coat,breed,dateOfBirth,registrationNumber,microchipNumber,passportNumber,height + horseName,sex,coat,breed,dateOfBirth,registrationNumber,microchipNumber,passportNumber,height @@ -123,7 +139,7 @@ Connect to 5s - false + true false @@ -187,13 +203,29 @@ Connect to 5s - - false - - + + true + + + + false + { + "name": "${name}", + "surname": "${surname}", + "email": "${email}", + "phoneNumber": "${phoneNumber}", + "address": "${address}", + "city": "${city}", + "state": "${state}", + "zipCode": "${zipCode}", + "country": "${country}" +} + = + + - /api/rest/repository/owner/v1/${ownerId} - GET + /api/rest/repository/owner/v1 + POST false false true @@ -204,12 +236,12 @@ Connect to 5s 6 false 0 - Servizio REST /api/rest/repository/owner/v1/${id} + Servizio REST /api/rest/repository/owner/v1 - + - 200 + 201 Assertion.response_code false @@ -229,24 +261,33 @@ Connect to 5s - .id - ${ownerId} - true + $.name + 0 + false false false false Check JSON Path and value + + createdOwnerId + id + 0 + 0 + Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getHorseById + + - + true false { - "name": "${name}", + "id": ${createdOwnerId}, + "name": "${name}-updated", "surname": "${surname}", "email": "${email}", "phoneNumber": "${phoneNumber}", @@ -261,7 +302,7 @@ Connect to 5s /api/rest/repository/owner/v1 - POST + PUT false false true @@ -275,9 +316,9 @@ Connect to 5s Servizio REST /api/rest/repository/owner/v1 - + - 201 + 200 Assertion.response_code false @@ -298,8 +339,8 @@ Connect to 5s $.name - 0 - false + ${name}-updated + true false false false @@ -315,40 +356,9 @@ Connect to 5s - - false - - - - /api/rest/repository/owner/v1/${ownerId} - DELETE - false - false - true - false - false - false - false - 6 - false - 0 - Servizio REST /api/rest/repository/owner/v1 - - - - - 204 - - Assertion.response_code - false - 1 - - - - - false + true false @@ -412,12 +422,12 @@ Connect to 5s - + false - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/owner/v1 GET false false @@ -429,7 +439,7 @@ Connect to 5s 6 false 0 - Servizio REST /api/rest/repository/horse/v1/${id} + Servizio REST /api/rest/repository/owner/v1 @@ -455,7 +465,7 @@ Connect to 5s .id - ${horseId} + ${ownerId} true false false @@ -463,14 +473,39 @@ Connect to 5s Check JSON Path and value + + ownerId + *.id + 0 + 0 + Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata createHorse + + - - false - - + + true + + + + false + { + "name": "${horseName}", + "sex": "${sex}", + "coat": "${coat}", + "breed": "${breed}", + "dateOfBirth": "${dateOfBirth}", + "registrationNumber": "${registrationNumber}", + "microchipNumber": "${microchipNumber}", + "passportNumber": "${passportNumber}", + "height": ${height}, + "owners": [{"id": ${createdOwnerId}}] +} + = + + - /api/rest/repository/owner/v1 - GET + /api/rest/repository/horse/v1 + POST false false true @@ -481,12 +516,12 @@ Connect to 5s 6 false 0 - Servizio REST /api/rest/repository/owner/v1 + Servizio REST /api/rest/repository/horse/v1 - + - 200 + 201 Assertion.response_code false @@ -506,32 +541,32 @@ Connect to 5s - .id - ${ownerId} - true + $.name + 0 + false false false false Check JSON Path and value - - ownerId - *.id + + createdHorseId + id 0 0 - Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata createHorse + Estrazione dell'identificativo dell'Horse. Il valore sarà utilizzato per la successiva chiamata getHorseById - + true false { - "name": "${name}", + "name": "${horseName}-updated", "sex": "${sex}", "coat": "${coat}", "breed": "${breed}", @@ -540,14 +575,14 @@ Connect to 5s "microchipNumber": "${microchipNumber}", "passportNumber": "${passportNumber}", "height": ${height}, - "owners": [{"id": ${ownerId}}] + "owners": [{"id": ${createdOwnerId}}] } = - /api/rest/repository/horse/v1 - POST + /api/rest/repository/horse/v1/${createdHorseId} + PUT false false true @@ -561,9 +596,9 @@ Connect to 5s Servizio REST /api/rest/repository/horse/v1 - + - 201 + 200 Assertion.response_code false @@ -584,8 +619,8 @@ Connect to 5s $.name - 0 - false + ${horseName}-updated + true false false false @@ -606,7 +641,7 @@ Connect to 5s - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/horse/v1/${createdHorseId} DELETE false false @@ -632,6 +667,37 @@ Connect to 5s + + false + + + + /api/rest/repository/owner/v1/${createdOwnerId} + DELETE + false + false + true + false + false + false + false + 6 + false + 0 + Servizio REST /api/rest/repository/owner/v1 + + + + + 204 + + Assertion.response_code + false + 1 + + + + @@ -652,7 +718,7 @@ Connect to 5s - false + true false @@ -718,20 +784,36 @@ Connect to 5s - - Servizio REST /api/rest/repository/owner/v1/${id} + + Servizio REST /api/rest/repository/owner/v1 false false 6 5000 30000 2.0.5 - false - - + true + + + + false + { + "name": "${name}", + "surname": "${surname}", + "email": "${email}", + "phoneNumber": "${phoneNumber}", + "address": "${address}", + "city": "${city}", + "state": "${state}", + "zipCode": "${zipCode}", + "country": "${country}" +} + = + + - /api/rest/repository/owner/v1/${ownerId} - GET + /api/rest/repository/owner/v1 + POST false false false @@ -740,9 +822,9 @@ Connect to 5s false - + - 200 + 201 Assertion.response_code false @@ -761,26 +843,26 @@ Connect to 5s - - .id - ${ownerId} - true - false - false - false - Check JSON Path and value - - - ownerId + createdOwnerId id 0 0 Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + + $.name + 0 + false + false + false + false + Check JSON Path and value + + - + Servizio REST /api/rest/repository/owner/v1 false false @@ -794,7 +876,8 @@ Connect to 5s false { - "name": "${name}", + "id": ${createdOwnerId}, + "name": "${name}-updated", "surname": "${surname}", "email": "${email}", "phoneNumber": "${phoneNumber}", @@ -809,7 +892,7 @@ Connect to 5s /api/rest/repository/owner/v1 - POST + PUT false false false @@ -818,9 +901,9 @@ Connect to 5s false - + - 201 + 200 Assertion.response_code false @@ -849,8 +932,8 @@ Connect to 5s $.name - 0 - false + ${name}-updated + true false false false @@ -858,8 +941,14 @@ Connect to 5s - - Servizio REST /api/rest/repository/owner/v1 + + + true + false + + + + Servizio REST /api/rest/repository/horse/v1 false false 6 @@ -870,8 +959,8 @@ Connect to 5s - /api/rest/repository/owner/v1/${ownerId} - DELETE + /api/rest/repository/horse/v1 + GET false false false @@ -880,46 +969,7 @@ Connect to 5s false - - - 204 - - Assertion.response_code - false - 1 - - - - - - - false - false - - - - Servizio REST /api/rest/repository/horse/v1 - false - false - 6 - 5000 - 30000 - 2.0.5 - false - - - - /api/rest/repository/horse/v1 - GET - false - false - false - false - false - false - - - + 200 @@ -959,8 +1009,8 @@ Connect to 5s - - Servizio REST /api/rest/repository/horse/v1/${id} + + Servizio REST /api/rest/repository/owner/v1 false false 6 @@ -971,7 +1021,7 @@ Connect to 5s - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/owner/v1 GET false false @@ -1003,30 +1053,55 @@ Connect to 5s - .id - ${horseId} - true + $[0].name + 0 + false false false false Check JSON Path and value + + ownerId + *.id + 0 + 0 + Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + + - - Servizio REST /api/rest/repository/owner/v1 + + Servizio REST /api/rest/repository/horse/v1 false false 6 5000 30000 2.0.5 - false - - + true + + + + false + { + "name": "${horseName}", + "sex": "${sex}", + "coat": "${coat}", + "breed": "${breed}", + "dateOfBirth": "${dateOfBirth}", + "registrationNumber": "${registrationNumber}", + "microchipNumber": "${microchipNumber}", + "passportNumber": "${passportNumber}", + "height": ${height}, + "owners": [{"id": ${createdOwnerId}}] +} + = + + - /api/rest/repository/owner/v1 - GET + /api/rest/repository/horse/v1 + POST false false false @@ -1035,9 +1110,9 @@ Connect to 5s false - + - 200 + 201 Assertion.response_code false @@ -1057,7 +1132,7 @@ Connect to 5s - $[0].name + $.name 0 false false @@ -1066,16 +1141,16 @@ Connect to 5s Check JSON Path and value - - ownerId - *.id + + createdHorseId + id 0 0 - Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + Estrazione dell'identificativo dell'Horse. Il valore sarà utilizzato per la successiva chiamata getHorseById - + Servizio REST /api/rest/repository/horse/v1 false false @@ -1089,7 +1164,7 @@ Connect to 5s false { - "name": "${name}", + "name": "${horseName}-updated", "sex": "${sex}", "coat": "${coat}", "breed": "${breed}", @@ -1098,14 +1173,14 @@ Connect to 5s "microchipNumber": "${microchipNumber}", "passportNumber": "${passportNumber}", "height": ${height}, - "owners": [{"id": ${ownerId}}] + "owners": [{"id": ${createdOwnerId}}] } = - /api/rest/repository/horse/v1 - POST + /api/rest/repository/horse/v1/${createdHorseId} + PUT false false false @@ -1114,9 +1189,9 @@ Connect to 5s false - + - 201 + 200 Assertion.response_code false @@ -1137,8 +1212,8 @@ Connect to 5s $.name - 0 - false + ${horseName}-updated + true false false false @@ -1146,7 +1221,7 @@ Connect to 5s - horseId + createdHorseId id 0 0 @@ -1166,7 +1241,40 @@ Connect to 5s - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/horse/v1/${createdHorseId} + DELETE + false + false + false + false + false + false + + + + + 204 + + Assertion.response_code + false + 1 + + + + + + Servizio REST /api/rest/repository/owner/v1 + false + false + 6 + 5000 + 30000 + 2.0.5 + false + + + + /api/rest/repository/owner/v1/${createdOwnerId} DELETE false false @@ -1216,7 +1324,7 @@ Connect to 5s - false + true false @@ -1282,20 +1390,36 @@ Connect to 5s - - Servizio REST /api/rest/repository/owner/v1/${id} + + Servizio REST /api/rest/repository/owner/v1 false false 6 5000 30000 2.0.5 - false - - + true + + + + false + { + "name": "${name}", + "surname": "${surname}", + "email": "${email}", + "phoneNumber": "${phoneNumber}", + "address": "${address}", + "city": "${city}", + "state": "${state}", + "zipCode": "${zipCode}", + "country": "${country}" +} + = + + - /api/rest/repository/owner/v1/${ownerId} - GET + /api/rest/repository/owner/v1 + POST false false false @@ -1304,9 +1428,9 @@ Connect to 5s false - + - 200 + 201 Assertion.response_code false @@ -1325,26 +1449,26 @@ Connect to 5s - - .id - ${ownerId} - true - false - false - false - Check JSON Path and value - - - ownerId + createdOwnerId id 0 0 Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + + $.name + 0 + false + false + false + false + Check JSON Path and value + + - + Servizio REST /api/rest/repository/owner/v1 false false @@ -1358,7 +1482,8 @@ Connect to 5s false { - "name": "${name}", + "id": ${createdOwnerId}, + "name": "${name}-updated", "surname": "${surname}", "email": "${email}", "phoneNumber": "${phoneNumber}", @@ -1373,7 +1498,7 @@ Connect to 5s /api/rest/repository/owner/v1 - POST + PUT false false false @@ -1382,9 +1507,9 @@ Connect to 5s false - + - 201 + 200 Assertion.response_code false @@ -1413,8 +1538,8 @@ Connect to 5s $.name - 0 - false + ${name}-updated + true false false false @@ -1422,42 +1547,9 @@ Connect to 5s - - Servizio REST /api/rest/repository/owner/v1 - false - false - 6 - 5000 - 30000 - 2.0.5 - false - - - - /api/rest/repository/owner/v1/${ownerId} - DELETE - false - false - false - false - false - false - - - - - 204 - - Assertion.response_code - false - 1 - - - - - false + true false @@ -1523,8 +1615,8 @@ Connect to 5s - - Servizio REST /api/rest/repository/horse/v1/${id} + + Servizio REST /api/rest/repository/owner/v1 false false 6 @@ -1535,7 +1627,7 @@ Connect to 5s - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/owner/v1 GET false false @@ -1567,30 +1659,55 @@ Connect to 5s - .id - ${horseId} - true + $[0].name + 0 + false false false false Check JSON Path and value + + ownerId + *.id + 0 + 0 + Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + + - - Servizio REST /api/rest/repository/owner/v1 + + Servizio REST /api/rest/repository/horse/v1 false false 6 5000 30000 2.0.5 - false - - + true + + + + false + { + "name": "${horseName}", + "sex": "${sex}", + "coat": "${coat}", + "breed": "${breed}", + "dateOfBirth": "${dateOfBirth}", + "registrationNumber": "${registrationNumber}", + "microchipNumber": "${microchipNumber}", + "passportNumber": "${passportNumber}", + "height": ${height}, + "owners": [{"id": ${createdOwnerId}}] +} + = + + - /api/rest/repository/owner/v1 - GET + /api/rest/repository/horse/v1 + POST false false false @@ -1599,9 +1716,9 @@ Connect to 5s false - + - 200 + 201 Assertion.response_code false @@ -1621,7 +1738,7 @@ Connect to 5s - $[0].name + $.name 0 false false @@ -1630,16 +1747,16 @@ Connect to 5s Check JSON Path and value - - ownerId - *.id + + createdHorseId + id 0 0 - Estrazione dell'identificativo dell'Owner. Il valore sarà utilizzato per la successiva chiamata getOwnerById + Estrazione dell'identificativo dell'Horse. Il valore sarà utilizzato per la successiva chiamata getHorseById - + Servizio REST /api/rest/repository/horse/v1 false false @@ -1653,7 +1770,7 @@ Connect to 5s false { - "name": "${name}", + "name": "${horseName}-updated", "sex": "${sex}", "coat": "${coat}", "breed": "${breed}", @@ -1662,14 +1779,14 @@ Connect to 5s "microchipNumber": "${microchipNumber}", "passportNumber": "${passportNumber}", "height": ${height}, - "owners": [{"id": ${ownerId}}] + "owners": [{"id": ${createdOwnerId}}] } = - /api/rest/repository/horse/v1 - POST + /api/rest/repository/horse/v1/${createdHorseId} + PUT false false false @@ -1678,9 +1795,9 @@ Connect to 5s false - + - 201 + 200 Assertion.response_code false @@ -1701,8 +1818,8 @@ Connect to 5s $.name - 0 - false + ${horseName}-updated + true false false false @@ -1710,7 +1827,7 @@ Connect to 5s - horseId + createdHorseId id 0 0 @@ -1730,7 +1847,40 @@ Connect to 5s - /api/rest/repository/horse/v1/${horseId} + /api/rest/repository/horse/v1/${createdHorseId} + DELETE + false + false + false + false + false + false + + + + + 204 + + Assertion.response_code + false + 1 + + + + + + Servizio REST /api/rest/repository/owner/v1 + false + false + 6 + 5000 + 30000 + 2.0.5 + false + + + + /api/rest/repository/owner/v1/${createdOwnerId} DELETE false false @@ -1754,7 +1904,7 @@ Connect to 5s - true + false saveConfig