diff --git a/extensions/datasource/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/datasource/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 4004eb6e31ba2..d727e12bff51d 100644 --- a/extensions/datasource/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/datasource/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -8,4 +8,6 @@ metadata: categories: - "data" status: "stable" - unlisted: true \ No newline at end of file + unlisted: true + config: + - "quarkus.datasource." \ No newline at end of file diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevUIConfig.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIConfig.java similarity index 91% rename from extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevUIConfig.java rename to extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIConfig.java index 828db66ef474c..9b9415a33688d 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevUIConfig.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIConfig.java @@ -1,4 +1,4 @@ -package io.quarkus.vertx.http.deployment.devmode.console; +package io.quarkus.devui.deployment; import io.quarkus.runtime.annotations.ConfigGroup; import io.quarkus.runtime.annotations.ConfigItem; diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIProcessor.java index f57d61b6f898b..e8efc2401e762 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/DevUIProcessor.java @@ -68,6 +68,7 @@ import io.quarkus.vertx.http.deployment.webjar.WebJarBuildItem; import io.quarkus.vertx.http.deployment.webjar.WebJarResourcesFilter; import io.quarkus.vertx.http.deployment.webjar.WebJarResultsBuildItem; +import io.quarkus.vertx.http.runtime.devmode.DevConsoleCORSFilter; import io.smallrye.common.annotation.Blocking; import io.smallrye.common.annotation.NonBlocking; import io.smallrye.mutiny.Multi; @@ -120,6 +121,7 @@ public class DevUIProcessor { @BuildStep(onlyIf = IsDevelopment.class) @Record(ExecutionTime.STATIC_INIT) void registerDevUiHandlers( + DevUIConfig devUIConfig, MvnpmBuildItem mvnpmBuildItem, List devUIRoutesBuildItems, List staticContentBuildItems, @@ -133,6 +135,13 @@ void registerDevUiHandlers( return; } + if (devUIConfig.cors.enabled) { + routeProducer.produce(nonApplicationRootPathBuildItem.routeBuilder() + .route(DEVUI + SLASH_ALL) + .handler(new DevConsoleCORSFilter()) + .build()); + } + // Websocket for JsonRPC comms routeProducer.produce( nonApplicationRootPathBuildItem @@ -155,8 +164,8 @@ void registerDevUiHandlers( .route(route) .handler(uihandler); - if (route.endsWith(DEVUI)) { - builder = builder.displayOnNotFoundPage("Dev UI 2.0"); + if (route.endsWith(DEVUI + SLASH)) { + builder = builder.displayOnNotFoundPage("Dev UI (v2)"); routeProducer.produce(builder.build()); } diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ConfigurationProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ConfigurationProcessor.java index 4f03b2b204568..a98365dbde3f7 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ConfigurationProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ConfigurationProcessor.java @@ -2,26 +2,43 @@ import static io.quarkus.vertx.http.deployment.devmode.console.ConfigEditorProcessor.cleanUpAsciiDocIfNecessary; import static io.quarkus.vertx.http.deployment.devmode.console.ConfigEditorProcessor.isSetByDevServices; +import static io.smallrye.config.Expressions.withoutExpansion; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.config.spi.ConfigSource; + import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.ConfigDescriptionBuildItem; import io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem; +import io.quarkus.dev.console.DevConsoleManager; import io.quarkus.devui.deployment.InternalPageBuildItem; +import io.quarkus.devui.runtime.config.ConfigJsonRPCService; +import io.quarkus.devui.spi.JsonRPCProvidersBuildItem; import io.quarkus.devui.spi.page.Page; +import io.quarkus.vertx.http.deployment.devmode.console.ConfigEditorProcessor; import io.quarkus.vertx.http.runtime.devmode.ConfigDescription; +import io.smallrye.config.SmallRyeConfig; /** * This creates Extensions Page */ public class ConfigurationProcessor { + private static final String QUOTED_DOT = "\".\""; + private static final String QUOTED_DOT_KEY = "$$QUOTED_DOT$$"; + @BuildStep(onlyIf = IsDevelopment.class) InternalPageBuildItem createConfigurationPages(List configDescriptionBuildItems, Optional devServicesLauncherConfig) { @@ -46,6 +63,16 @@ InternalPageBuildItem createConfigurationPages(List return configurationPages; } + @BuildStep(onlyIf = IsDevelopment.class) + JsonRPCProvidersBuildItem registerJsonRpcService() { + DevConsoleManager.register("config-update-property", map -> { + Map values = Collections.singletonMap(map.get("name"), map.get("value")); + ConfigEditorProcessor.updateConfig(values); + return null; + }); + return new JsonRPCProvidersBuildItem("devui-configuration", ConfigJsonRPCService.class); + } + private List getAllConfig(List configDescriptionBuildItems, Optional devServicesLauncherConfig) { List configDescriptions = new ArrayList<>(); @@ -59,7 +86,220 @@ private List getAllConfig(List co item.getAllowedValues(), item.getConfigPhase().name())); } - return configDescriptions; + + Set devServicesConfig = new HashSet<>(); + if (devServicesLauncherConfig.isPresent()) { + devServicesConfig.addAll(devServicesLauncherConfig.get().getConfig().keySet()); + } + + return calculate(configDescriptions, devServicesConfig); + } + + private List calculate(List cd, Set devServicesProperties) { + List configDescriptions = new ArrayList<>(cd); + + List ordered = new ArrayList<>(); + List properties = new ArrayList<>(); + SmallRyeConfig current = (SmallRyeConfig) ConfigProvider.getConfig(); + + Map, Set> allPropertySegments = new HashMap<>(); + Set propertyNames = new HashSet<>(); + current.getPropertyNames().forEach(propertyNames::add); + for (String propertyName : propertyNames) { + propertyName = propertyName.replace(QUOTED_DOT, QUOTED_DOT_KEY); // Make sure dots can be quoted + String[] parts = propertyName.split("\\."); + + List accumulate = new ArrayList<>(); + //we never want to add the full string + //hence -1 + for (int i = 0; i < parts.length - 1; ++i) { + if (parts[i].isEmpty()) { + //this can't map to a quarkus prop as it has an empty segment + //so skip + break; + } + // If there was a quoted dot, put that back + if (parts[i].contains(QUOTED_DOT_KEY)) { + parts[i] = parts[i].replaceAll(QUOTED_DOT_KEY, QUOTED_DOT); + } + + accumulate.add(parts[i]); + //if there is both a quoted and unquoted version we only want to apply the quoted version + //and remove the unquoted one + Set potentialSegmentSet = allPropertySegments.computeIfAbsent(List.copyOf(accumulate), + (k) -> new HashSet<>()); + if (isQuoted(parts[i + 1])) { + potentialSegmentSet.add(parts[i + 1]); + potentialSegmentSet.remove(parts[i + 1].substring(1, parts[i + 1].length() - 1)); + } else { + if (!potentialSegmentSet.contains(ensureQuoted(parts[i + 1]))) { + potentialSegmentSet.add(parts[i + 1]); + } + } + + } + } + + Map, Set> wildcardsToAdd = new HashMap<>(); + Map foundItems = new HashMap<>(); + Set bannedExpansionCombos = new HashSet<>(); + //we iterate over every config description + for (ConfigDescription item : configDescriptions) { + //if they are a non-wildcard description we just add them directly + if (!item.getName().contains("{*}")) { + //we don't want to accidentally use these properties as name expansions + //we ban them which means that the only way the name can be expanded into a map + //is if it is quoted + bannedExpansionCombos.add(item.getName()); + for (int i = 0; i < item.getName().length(); ++i) { + //add all possible segments to the banned list + if (item.getName().charAt(i) == '.') { + bannedExpansionCombos.add(item.getName().substring(0, i)); + } + } + properties.add(item.getName()); + item.setConfigValue(current.getConfigValue(item.getName())); + ordered.add(item); + } else if (!item.getName().startsWith("quarkus.log.filter")) { //special case, we use this internally and we don't want it clogging up the editor + //we need to figure out how to expand it + //this can have multiple stars + List> componentParts = new ArrayList<>(); + List accumulator = new ArrayList<>(); + //keys that were used to expand, checked against the banned list before adding + for (var i : item.getName().split("\\.")) { + if (i.equals("{*}")) { + componentParts.add(accumulator); + accumulator = new ArrayList<>(); + } else { + accumulator.add(i); + } + } + //note that accumulator is still holding the final part + //we need it later, but we don't want it in this loop + Map, Set> building = new HashMap<>(); + building.put(List.of(), new HashSet<>()); + for (List currentPart : componentParts) { + Map, Set> newBuilding = new HashMap<>(); + for (Map.Entry, Set> entry : building.entrySet()) { + List attempt = entry.getKey(); + List newBase = new ArrayList<>(attempt); + newBase.addAll(currentPart); + wildcardsToAdd.put(newBase, entry.getValue()); + Set potential = allPropertySegments.get(newBase); + if (potential != null) { + bannedExpansionCombos.add(String.join(".", newBase).replace("\"", "")); + for (String definedName : potential) { + List toAdd = new ArrayList<>(newBase); + toAdd.add(definedName); + //for expansion keys we always use unquoted values, same with banned + //so we are always comparing unquoted + Set expansionKeys = new HashSet<>(entry.getValue()); + expansionKeys.add(String.join(".", newBase) + "." + definedName); + newBuilding.put(toAdd, expansionKeys); + } + } + } + building = newBuilding; + } + //now we have our config properties + for (var entry : building.entrySet()) { + List segments = entry.getKey(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < segments.size(); ++i) { + if (i > 0) { + sb.append("."); + } + sb.append(segments.get(i)); + } + //accumulator holds the find string + for (String s : accumulator) { + sb.append(".").append(s); + } + String expandedName = sb.toString(); + foundItems.put(expandedName, new Holder(entry.getValue(), item)); + } + } + } + for (Map.Entry e : foundItems.entrySet()) { + boolean ok = true; + for (String key : e.getValue().expansionKeys) { + if (bannedExpansionCombos.contains(key)) { + ok = false; + break; + } + } + if (!ok) { + continue; + } + String expandedName = e.getKey(); + var item = e.getValue().configDescription; + ConfigDescription newDesc = new ConfigDescription(expandedName, item.getDescription(), + item.getDefaultValue(), devServicesProperties.contains(expandedName), item.getTypeName(), + item.getAllowedValues(), + item.getConfigPhase()); + + properties.add(newDesc.getName()); + newDesc.setConfigValue(current.getConfigValue(newDesc.getName())); + ordered.add(newDesc); + } + + //now add our star properties + for (var entry : wildcardsToAdd.entrySet()) { + boolean ok = true; + for (String key : entry.getValue()) { + if (bannedExpansionCombos.contains(key)) { + ok = false; + break; + } + } + if (!ok) { + continue; + } + List segments = entry.getKey(); + StringBuilder sb = new StringBuilder(); + for (String segment : segments) { + sb.append(segment); + sb.append("."); + } + String expandedName = sb.toString(); + ConfigDescription newDesc = new ConfigDescription(expandedName, true); + + properties.add(newDesc.getName()); + newDesc.setConfigValue(current.getConfigValue(newDesc.getName())); + ordered.add(newDesc); + } + + for (ConfigSource configSource : current.getConfigSources()) { + if (configSource.getName().equals("PropertiesConfigSource[source=Build system]")) { + properties.addAll(configSource.getPropertyNames()); + } + } + + withoutExpansion(() -> { + for (String propertyName : current.getPropertyNames()) { + if (properties.contains(propertyName)) { + continue; + } + + ConfigDescription item = new ConfigDescription(propertyName, null, null, current.getConfigValue(propertyName)); + ordered.add(item); + + configDescriptions.add(item); + } + }); + + return ordered; + } + + private String ensureQuoted(String part) { + if (isQuoted(part)) { + return part; + } + return "\"" + part + "\""; + } + + private boolean isQuoted(String part) { + return part.length() >= 2 && part.charAt(0) == '\"' && part.charAt(part.length() - 1) == '\"'; } private static final Pattern codePattern = Pattern.compile("(\\{@code )([^}]+)(\\})"); @@ -77,4 +317,14 @@ static String formatJavadoc(String val) { val = val.replace("@deprecated", "
Deprecated"); return val; } + + static class Holder { + final Set expansionKeys; + final ConfigDescription configDescription; + + private Holder(Set expansionKeys, ConfigDescription configDescription) { + this.expansionKeys = expansionKeys; + this.configDescription = configDescription; + } + } } diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/ConfigEditorProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/ConfigEditorProcessor.java index 07c324325043b..9825d2090f6b2 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/ConfigEditorProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/ConfigEditorProcessor.java @@ -8,7 +8,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -44,8 +43,6 @@ import io.quarkus.devconsole.runtime.spi.DevConsolePostHandler; import io.quarkus.devconsole.spi.DevConsoleRouteBuildItem; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; -import io.quarkus.devui.runtime.config.ConfigJsonRPCService; -import io.quarkus.devui.spi.JsonRPCProvidersBuildItem; import io.quarkus.vertx.http.runtime.devmode.ConfigDescription; import io.quarkus.vertx.http.runtime.devmode.ConfigDescriptionsManager; import io.quarkus.vertx.http.runtime.devmode.ConfigDescriptionsRecorder; @@ -120,7 +117,6 @@ protected void handlePost(RoutingContext event, MultiMap form) throws Exception updateConfig(autoconfig); } else if (action.equals("updateProperties")) { - Map properties = new LinkedHashMap<>(); String values = event.request().getFormAttribute("values"); setConfig(values); } @@ -154,16 +150,6 @@ void handleRequests(BuildProducer devConsoleRouteProdu })); } - @BuildStep(onlyIf = IsDevelopment.class) - JsonRPCProvidersBuildItem registerJsonRpcService() { - DevConsoleManager.register("config-update-property", map -> { - Map values = Collections.singletonMap(map.get("name"), map.get("value")); - updateConfig(values); - return null; - }); - return new JsonRPCProvidersBuildItem("devui-configuration", ConfigJsonRPCService.class); - } - private Map filterAndApplyProfile(Map autoconfig, List configFilter, String profile) { return autoconfig.entrySet().stream() @@ -255,7 +241,6 @@ public static void updateConfig(Map values) { writer.newLine(); } } - preventKill(); } catch (Throwable t) { throw new RuntimeException(t); } @@ -272,22 +257,11 @@ static void setConfig(String value) { writer.write(value); } } - preventKill(); } catch (Throwable t) { throw new RuntimeException(t); } } - private static void preventKill() throws Exception { - //if we don't set this the connection will be killed on restart - DevConsoleManager.setDoingHttpInitiatedReload(true); - try { - DevConsoleManager.getHotReplacementContext().doScan(true); - } finally { - DevConsoleManager.setDoingHttpInitiatedReload(false); - } - } - private static Path getConfigPath() throws IOException { List resourcesDir = DevConsoleManager.getHotReplacementContext().getResourcesDir(); if (resourcesDir.isEmpty()) { diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java index ef12ca50856a9..a0b916db7b0fc 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java @@ -65,6 +65,7 @@ import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; import io.quarkus.devconsole.spi.DevConsoleTemplateInfoBuildItem; import io.quarkus.devconsole.spi.DevConsoleWebjarBuildItem; +import io.quarkus.devui.deployment.DevUIConfig; import io.quarkus.maven.dependency.ArtifactKey; import io.quarkus.maven.dependency.GACT; import io.quarkus.netty.runtime.virtual.VirtualChannel; diff --git a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/controller/jsonrpc.js b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/controller/jsonrpc.js index 0a097a92baa9f..c41215df3952d 100644 --- a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/controller/jsonrpc.js +++ b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/controller/jsonrpc.js @@ -249,10 +249,11 @@ export class JsonRpc { if (messageType === MessageType.Void.toString()) { // Void response, typically used on initial subscription // Do nothing - } else if (messageType === MessageType.HotReload.toString()){ - connectionState.hotreload(JsonRpc.serverUri); - connectionState.connected(JsonRpc.serverUri) - } else if (messageType === MessageType.Response.toString()) { // Normal Request-Response + } else if (messageType === MessageType.HotReload.toString() || messageType === MessageType.Response.toString()) { + if (messageType === MessageType.HotReload.toString()){ + connectionState.hotreload(JsonRpc.serverUri); + connectionState.connected(JsonRpc.serverUri); + } if (JsonRpc.promiseQueue.has(response.id)) { var saved = JsonRpc.promiseQueue.get(response.id); var promise = saved.promise; diff --git a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-configuration.js b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-configuration.js index 36cc482fe1e84..00cb0358a5833 100644 --- a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-configuration.js +++ b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-configuration.js @@ -131,7 +131,7 @@ export class QwcConfiguration extends observeState(LitElement) { _filterTextChanged(e) { const searchTerm = (e.detail.value || '').trim(); if (searchTerm === '') { - this._filtered = devuiState.allConfiguration + this._filtered = devuiState.allConfiguration; return; } @@ -208,7 +208,7 @@ export class QwcConfiguration extends observeState(LitElement) { - ` + `; } if (prop.wildcardEntry) { @@ -216,7 +216,7 @@ export class QwcConfiguration extends observeState(LitElement) { - ` + `; } return html` @@ -336,12 +336,13 @@ export class QwcConfiguration extends observeState(LitElement) { if (prop.defaultValue) { def = "Default value: " + prop.defaultValue; } - + let src = "Config source: " + prop.configValue.sourceName; return html`

${unsafeHTML(prop.description)}

Environment variable: ${res}
- ${unsafeHTML(def)} + ${unsafeHTML(def)}
+ ${unsafeHTML(src)}
`; } diff --git a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-extension.js b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-extension.js index d6162d2d9b7c9..d1fe10a11e701 100644 --- a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-extension.js +++ b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-extension.js @@ -141,15 +141,23 @@ export class QwcExtension extends LitElement { _footerTemplate() { return html` `; } + _renderConfigFilterIcon(){ + if(this.configFilter){ + return html` + + `; + }else{ + return html``; + } + } + _renderStatus(){ var l = this._statusLevelOnCard(); diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcMessage.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcMessage.java new file mode 100644 index 0000000000000..2e7428a72cc93 --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcMessage.java @@ -0,0 +1,35 @@ +package io.quarkus.devui.runtime.comms; + +/** + * Allows JSON RPC methods to response with more finer grade message types + * + * @param The type of the response object + */ +public class JsonRpcMessage { + private T response; + private MessageType messageType; + + public JsonRpcMessage() { + } + + public JsonRpcMessage(T response, MessageType messageType) { + this.response = response; + this.messageType = messageType; + } + + public T getResponse() { + return response; + } + + public void setResponse(T response) { + this.response = response; + } + + public MessageType getMessageType() { + return messageType; + } + + public void setMessageType(MessageType messageType) { + this.messageType = messageType; + } +} \ No newline at end of file diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcRouter.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcRouter.java index b55dc0e71fe39..dd29949c732ba 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcRouter.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/JsonRpcRouter.java @@ -1,7 +1,5 @@ package io.quarkus.devui.runtime.comms; -import static io.quarkus.devui.runtime.jsonrpc.JsonRpcKeys.MessageType; - import java.lang.reflect.Method; import java.time.LocalDateTime; import java.util.ArrayList; @@ -199,8 +197,14 @@ private void route(JsonRpcRequest jsonRpcRequest, ServerWebSocket s) { } uni.subscribe() .with(item -> { - codec.writeResponse(s, jsonRpcRequest.getId(), item, - MessageType.Response); + if (JsonRpcMessage.class.isAssignableFrom(item.getClass())) { + JsonRpcMessage jsonRpcMessage = (JsonRpcMessage) item; + codec.writeResponse(s, jsonRpcRequest.getId(), jsonRpcMessage.getResponse(), + jsonRpcMessage.getMessageType()); + } else { + codec.writeResponse(s, jsonRpcRequest.getId(), item, + MessageType.Response); + } }, failure -> { codec.writeErrorResponse(s, jsonRpcRequest.getId(), jsonRpcMethodName, failure); }); diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/MessageType.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/MessageType.java new file mode 100644 index 0000000000000..b6856874b052d --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/comms/MessageType.java @@ -0,0 +1,8 @@ +package io.quarkus.devui.runtime.comms; + +public enum MessageType { + Void, + Response, + SubscriptionMessage, + HotReload +} \ No newline at end of file diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/config/ConfigJsonRPCService.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/config/ConfigJsonRPCService.java index bd00385cf577d..04c296e282b75 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/config/ConfigJsonRPCService.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/config/ConfigJsonRPCService.java @@ -8,14 +8,16 @@ import org.eclipse.microprofile.config.ConfigProvider; import io.quarkus.dev.console.DevConsoleManager; +import io.quarkus.devui.runtime.comms.JsonRpcMessage; +import io.quarkus.devui.runtime.comms.MessageType; import io.vertx.core.json.JsonObject; @ApplicationScoped public class ConfigJsonRPCService { - public boolean updateProperty(String name, String value) { + public JsonRpcMessage updateProperty(String name, String value) { DevConsoleManager.invoke("config-update-property", Map.of("name", name, "value", value)); - return true; + return new JsonRpcMessage(true, MessageType.HotReload); } public JsonObject getAllValues() { diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcCodec.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcCodec.java index d7c1c601233ef..662d8e6a2e7c6 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcCodec.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcCodec.java @@ -2,8 +2,8 @@ import static io.quarkus.devui.runtime.jsonrpc.JsonRpcKeys.INTERNAL_ERROR; import static io.quarkus.devui.runtime.jsonrpc.JsonRpcKeys.METHOD_NOT_FOUND; -import static io.quarkus.devui.runtime.jsonrpc.JsonRpcKeys.MessageType; +import io.quarkus.devui.runtime.comms.MessageType; import io.quarkus.devui.runtime.jsonrpc.json.JsonMapper; import io.vertx.core.http.ServerWebSocket; import io.vertx.core.json.JsonObject; diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcKeys.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcKeys.java index d027420f55492..0902b35c208b4 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcKeys.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/jsonrpc/JsonRpcKeys.java @@ -20,10 +20,4 @@ public interface JsonRpcKeys { public static final int INVALID_PARAMS = -32602; // Invalid params. Invalid method parameter(s). public static final int INTERNAL_ERROR = -32603; // Internal error. Internal JSON-RPC error. - public static enum MessageType { - Void, - Response, - SubscriptionMessage, - HotReload - } } \ No newline at end of file