This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new e8265f72c85 CAMEL-20617: rest dev console e8265f72c85 is described below commit e8265f72c850209ab4eabd400a4f65fadefdec43 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sat Jun 15 10:59:17 2024 +0200 CAMEL-20617: rest dev console --- .../rest/openapi/RestOpenApiEndpoint.java | 4 +- .../rest/openapi/RestOpenApiProcessor.java | 61 ++++++++---- .../camel/component/rest/DefaultRestRegistry.java | 17 +++- .../org/apache/camel/dev-console/rest.json | 15 +++ .../services/org/apache/camel/dev-console/rest | 2 + .../org/apache/camel/dev-consoles.properties | 2 +- .../apache/camel/impl/console/RestDevConsole.java | 102 +++++++++++++++++++++ 7 files changed, 179 insertions(+), 24 deletions(-) diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java index cfcaf9a293f..ad68fe5c01d 100644 --- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java +++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java @@ -210,7 +210,9 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { RestOpenApiProcessor target = new RestOpenApiProcessor(this, doc, path, apiContextPath, processor, restOpenapiProcessorStrategy); CamelContextAware.trySetCamelContext(target, getCamelContext()); - return createConsumerFor(path, target); + Consumer consumer = createConsumerFor(path, target); + target.setConsumer(consumer); + return consumer; } protected Consumer createConsumerFor(String basePath, RestOpenApiProcessor processor) throws Exception { diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java index d9873587b2f..6d0735ed33f 100644 --- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java +++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java @@ -33,8 +33,10 @@ import io.swagger.v3.oas.models.parameters.Parameter; import org.apache.camel.AsyncCallback; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; +import org.apache.camel.Consumer; import org.apache.camel.Exchange; import org.apache.camel.Processor; +import org.apache.camel.RouteAware; import org.apache.camel.StartupStep; import org.apache.camel.component.platform.http.spi.PlatformHttpConsumerAware; import org.apache.camel.http.base.HttpHelper; @@ -69,6 +71,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came private final AtomicBoolean packageScanInit = new AtomicBoolean(); private final Set<Class<?>> scannedClasses = new HashSet<>(); private PlatformHttpConsumerAware platformHttpConsumer; + private Consumer consumer; public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, String apiContextPath, Processor processor, RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) { @@ -99,6 +102,14 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came this.platformHttpConsumer = platformHttpConsumer; } + public Consumer getConsumer() { + return consumer; + } + + public void setConsumer(Consumer consumer) { + this.consumer = consumer; + } + @Override public boolean process(Exchange exchange, AsyncCallback callback) { // use HTTP_URI as this works for all runtimes @@ -149,8 +160,8 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came } @Override - protected void doBuild() throws Exception { - super.doBuild(); + protected void doInit() throws Exception { + super.doInit(); CamelContextAware.trySetCamelContext(restOpenapiProcessorStrategy, getCamelContext()); @@ -160,16 +171,42 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came for (var o : e.getValue().readOperationsMap().entrySet()) { String v = o.getKey().name(); // verb // create per operation binding - RestBindingAdvice binding = createRestBinding(o.getValue()); + RestBindingConfiguration bc = createRestBindingConfiguration(o.getValue()); + + String url = basePath + path; + if (platformHttpConsumer != null) { + url = platformHttpConsumer.getPlatformHttpConsumer().getEndpoint().getServiceUrl() + url; + } + + String desc = o.getValue().getSummary(); + if (desc != null && desc.isBlank()) { + desc = null; + } + String routeId = null; + if (consumer instanceof RouteAware ra) { + routeId = ra.getRoute().getRouteId(); + } + camelContext.getRestRegistry().addRestService(consumer, url, path, basePath, null, v, bc.getConsumes(), + bc.getProduces(), bc.getType(), bc.getOutType(), routeId, desc); + + RestBindingAdvice binding = RestBindingAdviceFactory.build(camelContext, bc); + RestBindingAdviceFactory.build(camelContext, bc); + ServiceHelper.buildService(binding); paths.add(new RestOpenApiConsumerPath(v, path, o.getValue(), binding)); } } scannedClasses.clear(); // no longer needed - ServiceHelper.buildService(restOpenapiProcessorStrategy); + + restOpenapiProcessorStrategy.setMissingOperation(endpoint.getMissingOperation()); + restOpenapiProcessorStrategy.setMockIncludePattern(endpoint.getMockIncludePattern()); + ServiceHelper.initService(restOpenapiProcessorStrategy); + + // validate openapi contract + restOpenapiProcessorStrategy.validateOpenApi(openAPI, platformHttpConsumer); } - private RestBindingAdvice createRestBinding(Operation o) throws Exception { + private RestBindingConfiguration createRestBindingConfiguration(Operation o) throws Exception { RestConfiguration config = camelContext.getRestConfiguration(); RestConfiguration.RestBindingMode mode = config.getBindingMode(); @@ -301,7 +338,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came } } - return RestBindingAdviceFactory.build(camelContext, bc); + return bc; } private Class<?> loadBindingClass(CamelContext camelContext, String ref) { @@ -339,18 +376,6 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came return null; } - @Override - protected void doInit() throws Exception { - super.doInit(); - - restOpenapiProcessorStrategy.setMissingOperation(endpoint.getMissingOperation()); - restOpenapiProcessorStrategy.setMockIncludePattern(endpoint.getMockIncludePattern()); - ServiceHelper.initService(restOpenapiProcessorStrategy); - - // validate openapi contract - restOpenapiProcessorStrategy.validateOpenApi(openAPI, platformHttpConsumer); - } - @Override protected void doStart() throws Exception { super.doStart(); diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java index b4071655d07..1109d180500 100644 --- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java +++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/DefaultRestRegistry.java @@ -43,7 +43,7 @@ import org.apache.camel.util.ObjectHelper; public class DefaultRestRegistry extends ServiceSupport implements StaticService, RestRegistry, CamelContextAware { private CamelContext camelContext; - private final Map<Consumer, RestService> registry = new LinkedHashMap<>(); + private final Map<Consumer, List<RestService>> registry = new LinkedHashMap<>(); private transient Producer apiProducer; @Override @@ -52,7 +52,8 @@ public class DefaultRestRegistry extends ServiceSupport implements StaticService String consumes, String produces, String inType, String outType, String routeId, String description) { RestServiceEntry entry = new RestServiceEntry( consumer, url, baseUrl, basePath, uriTemplate, method, consumes, produces, inType, outType, description); - registry.put(consumer, entry); + List<RestService> list = registry.computeIfAbsent(consumer, c -> new ArrayList<>()); + list.add(entry); } @Override @@ -62,12 +63,20 @@ public class DefaultRestRegistry extends ServiceSupport implements StaticService @Override public List<RestRegistry.RestService> listAllRestServices() { - return new ArrayList<>(registry.values()); + List<RestRegistry.RestService> answer = new ArrayList<>(); + for (var list : registry.values()) { + answer.addAll(list); + } + return answer; } @Override public int size() { - return registry.size(); + int count = 0; + for (var list : registry.values()) { + count += list.size(); + } + return count; } @Override diff --git a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/rest.json b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/rest.json new file mode 100644 index 00000000000..552cda4ab75 --- /dev/null +++ b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/rest.json @@ -0,0 +1,15 @@ +{ + "console": { + "kind": "console", + "group": "camel", + "name": "rest", + "title": "Rest", + "description": "Rest DSL Registry information", + "deprecated": false, + "javaType": "org.apache.camel.impl.console.RestDevConsole", + "groupId": "org.apache.camel", + "artifactId": "camel-console", + "version": "4.7.0-SNAPSHOT" + } +} + diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/rest b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/rest new file mode 100644 index 00000000000..ac2ac639ecc --- /dev/null +++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/rest @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.impl.console.RestDevConsole diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties index 8462c8e6fdd..a4866c14bd6 100644 --- a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties +++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties @@ -1,5 +1,5 @@ # Generated by camel build tools - do NOT edit this file! -dev-consoles=bean blocked circuit-breaker consumer context debug endpoint event gc health inflight java-security jvm log memory properties reload route route-controller route-dump service source startup-recorder thread top trace transformers type-converters variables +dev-consoles=bean blocked circuit-breaker consumer context debug endpoint event gc health inflight java-security jvm log memory properties reload rest route route-controller route-dump service source startup-recorder thread top trace transformers type-converters variables groupId=org.apache.camel artifactId=camel-console version=4.7.0-SNAPSHOT diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java new file mode 100644 index 00000000000..eb9ef663600 --- /dev/null +++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/RestDevConsole.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.impl.console; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.camel.spi.RestRegistry; +import org.apache.camel.spi.annotations.DevConsole; +import org.apache.camel.support.console.AbstractDevConsole; +import org.apache.camel.util.json.JsonObject; + +@DevConsole(name = "rest", displayName = "Rest", description = "Rest DSL Registry information") +public class RestDevConsole extends AbstractDevConsole { + + public RestDevConsole() { + super("camel", "rest", "Rest", "Rest DSL Registry information"); + } + + @Override + protected String doCallText(Map<String, Object> options) { + StringBuilder sb = new StringBuilder(); + + RestRegistry rr = getCamelContext().getRestRegistry(); + for (RestRegistry.RestService rs : rr.listAllRestServices()) { + if (!sb.isEmpty()) { + sb.append("\n"); + } + sb.append(String.format("\n Url: %s", rs.getUrl())); + sb.append(String.format("\n Method: %s", rs.getMethod())); + sb.append(String.format("\n State: %s", rs.getState())); + if (rs.getConsumes() != null) { + sb.append(String.format("\n Consumes: %s", rs.getConsumes())); + } + if (rs.getProduces() != null) { + sb.append(String.format("\n Produces: %s", rs.getProduces())); + } + if (rs.getInType() != null) { + sb.append(String.format("\n In Type: %s", rs.getInType())); + } + if (rs.getOutType() != null) { + sb.append(String.format("\n Out Type: %s", rs.getOutType())); + } + if (rs.getDescription() != null) { + sb.append(String.format("\n Description: %s", rs.getDescription())); + } + } + sb.append("\n"); + + return sb.toString(); + } + + @Override + protected Map<String, Object> doCallJson(Map<String, Object> options) { + JsonObject root = new JsonObject(); + + List<JsonObject> list = new ArrayList<>(); + root.put("rests", list); + + RestRegistry rr = getCamelContext().getRestRegistry(); + for (RestRegistry.RestService rs : rr.listAllRestServices()) { + JsonObject jo = new JsonObject(); + jo.put("url", rs.getUrl()); + jo.put("method", rs.getMethod()); + jo.put("state", rs.getState()); + if (rs.getConsumes() != null) { + jo.put("consumes", rs.getConsumes()); + } + if (rs.getProduces() != null) { + jo.put("produces", rs.getProduces()); + } + if (rs.getInType() != null) { + jo.put("inType", rs.getInType()); + } + if (rs.getOutType() != null) { + jo.put("outType", rs.getOutType()); + } + if (rs.getDescription() != null) { + jo.put("description", rs.getDescription()); + } + list.add(jo); + } + + return root; + } + +}