From 745d1fdb4edd17dfb9e5f19c3b138d4beebab1c5 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Thu, 25 Feb 2021 12:30:51 +0100 Subject: [PATCH] Dev UI - minor improvements - throw an exception instead of NOT_FOUND, resolves #14872 - sort beans and observers, application components go first - show shortened package where appropriate --- .../deployment/dev/console/ClassName.java | 68 ++++++++++++++++++ .../arc/deployment/devconsole/ClassName.java | 29 -------- .../deployment/devconsole/DevBeanInfo.java | 70 ++++++++----------- .../devconsole/DevConsoleProcessor.java | 45 +++++++----- .../devconsole/DevObserverInfo.java | 37 ++++++---- .../main/resources/dev-templates/beans.html | 3 +- .../resources/dev-templates/embedded.html | 6 +- .../resources/dev-templates/observers.html | 4 +- .../dev-templates/tags/bean-declaration.html | 6 +- .../dev-templates/tags/display-bean.html | 10 +-- .../resources/dev-templates/tags/tree.html | 4 +- .../arc/runtime/devconsole/Invocation.java | 26 +++++++ .../devmode/console/DevConsoleProcessor.java | 33 ++++++++- .../resources/dev-static/css/dev-console.css | 4 ++ .../vertx/http/devconsole/ClassNameTest.java | 27 +++++++ .../quarkus/arc/processor/BeanProcessor.java | 4 ++ 16 files changed, 257 insertions(+), 119 deletions(-) create mode 100644 core/deployment/src/main/java/io/quarkus/deployment/dev/console/ClassName.java delete mode 100644 extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java create mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/devconsole/ClassNameTest.java diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/console/ClassName.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/console/ClassName.java new file mode 100644 index 00000000000000..354909540d87bb --- /dev/null +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/console/ClassName.java @@ -0,0 +1,68 @@ +package io.quarkus.deployment.dev.console; + +import java.util.Objects; + +/** + * This class is used to represent a class in dev console templates. + */ +public class ClassName implements Comparable { + + private final String name; + + public ClassName(String name) { + this.name = Objects.requireNonNull(name); + } + + public String getName() { + return name; + } + + public String getLocalName() { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) { + return name.substring(lastDot + 1); + } + return name; + } + + public String getPackageName() { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) { + return name.substring(0, lastDot); + } + return ""; + } + + public String getShortenedPackageName() { + return shorten(getPackageName()); + } + + public String getShortenedName() { + return shorten(name); + } + + @Override + public int compareTo(ClassName other) { + return name.compareTo(other.name); + } + + @Override + public String toString() { + return name; + } + + private String shorten(String value) { + String[] parts = value.split("\\."); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < parts.length; i++) { + if (i == parts.length - 1) { + builder.append(parts[i]); + } else { + builder.append(parts[i].charAt(0)); + builder.append('.'); + } + } + return builder.toString(); + } + +} diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java deleted file mode 100644 index e25b632814bf9d..00000000000000 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/ClassName.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.quarkus.arc.deployment.devconsole; - -// FIXME: this should be a template extension method for String -public class ClassName { - private String name; - - public ClassName() { - } - - public ClassName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLocalName() { - int lastDot = name.lastIndexOf('.'); - if (lastDot != -1) { - return name.substring(lastDot + 1); - } - return name; - } -} diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java index f088c7c16aa7d7..55d8e3ebb2e0ca 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevBeanInfo.java @@ -1,42 +1,36 @@ package io.quarkus.arc.deployment.devconsole; -import java.util.ArrayList; import java.util.List; -public class DevBeanInfo implements Comparable { - - private ClassName name; - private String methodName; - private DevBeanKind kind; - private ClassName type; - private List qualifiers = new ArrayList<>(); - private ClassName scope; +import io.quarkus.deployment.dev.console.ClassName; - public DevBeanInfo() { - } +public class DevBeanInfo implements Comparable { - public DevBeanInfo(ClassName name, String methodName, ClassName type, List qualifiers, ClassName scope, - DevBeanKind kind) { - this.name = name; - this.methodName = methodName; + private final boolean isApplicationBean; + private final ClassName declaringClassName; + private final String memberName; + private final DevBeanKind kind; + // TODO this is more a raw type, i.e. we don't handle arrays, parameterized types, etc. + private final ClassName type; + private final List qualifiers; + private final ClassName scope; + + public DevBeanInfo(ClassName declaringClassName, String methodName, ClassName type, List qualifiers, + ClassName scope, + DevBeanKind kind, boolean isApplicationBean) { + this.declaringClassName = declaringClassName; + this.memberName = methodName; this.type = type; this.qualifiers = qualifiers; this.scope = scope; this.kind = kind; - } - - public void setKind(DevBeanKind kind) { - this.kind = kind; + this.isApplicationBean = isApplicationBean; } public DevBeanKind getKind() { return kind; } - public void setScope(ClassName scope) { - this.scope = scope; - } - public ClassName getScope() { return scope; } @@ -45,36 +39,28 @@ public List getQualifiers() { return qualifiers; } - public void setQualifiers(List qualifiers) { - this.qualifiers = qualifiers; - } - - public void setType(ClassName type) { - this.type = type; - } - public ClassName getType() { return type; } - public String getMethodName() { - return methodName; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; + public String getMemberName() { + return memberName; } - public void setName(ClassName name) { - this.name = name; + public ClassName getDeclaringClassName() { + return declaringClassName; } - public ClassName getName() { - return name; + public boolean isApplicationBean() { + return isApplicationBean; } @Override public int compareTo(DevBeanInfo o) { - return type.getLocalName().compareTo(o.type.getLocalName()); + // Application beans should go first + if (isApplicationBean == o.isApplicationBean) { + return type.compareTo(o.type); + } + return isApplicationBean ? -1 : 1; } } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java index c87ff32112c4cf..19fc310b0b82cf 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevConsoleProcessor.java @@ -18,6 +18,7 @@ import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; import io.quarkus.arc.deployment.ArcConfig; import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem; +import io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem; import io.quarkus.arc.deployment.CustomScopeAnnotationsBuildItem; import io.quarkus.arc.deployment.ValidationPhaseBuildItem; import io.quarkus.arc.processor.AnnotationsTransformer; @@ -38,6 +39,7 @@ import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.dev.console.ClassName; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; import io.quarkus.devconsole.spi.DevConsoleTemplateInfoBuildItem; @@ -94,22 +96,24 @@ public void transform(TransformationContext transformationContext) { } @BuildStep(onlyIf = IsDevelopment.class) - public DevConsoleTemplateInfoBuildItem collectBeanInfo(ValidationPhaseBuildItem validationPhaseBuildItem) { + public DevConsoleTemplateInfoBuildItem collectBeanInfo(ValidationPhaseBuildItem validationPhaseBuildItem, + CompletedApplicationClassPredicateBuildItem predicate) { BeanDeploymentValidator.ValidationContext validationContext = validationPhaseBuildItem.getContext(); DevBeanInfos beanInfos = new DevBeanInfos(); for (BeanInfo beanInfo : validationContext.beans()) { - beanInfos.addBean(createBeanInfo(beanInfo)); + beanInfos.addBean(createBeanInfo(beanInfo, predicate)); } for (BeanInfo beanInfo : validationContext.removedBeans()) { - beanInfos.addRemovedBean(createBeanInfo(beanInfo)); + beanInfos.addRemovedBean(createBeanInfo(beanInfo, predicate)); } for (ObserverInfo observerInfo : validationContext.get(BuildExtension.Key.OBSERVERS)) { - beanInfos.addObserver(createDevInfo(observerInfo)); + beanInfos.addObserver(createObserverInfo(observerInfo, predicate)); } + beanInfos.sort(); return new DevConsoleTemplateInfoBuildItem("devBeanInfos", beanInfos); } - private DevBeanInfo createBeanInfo(BeanInfo beanInfo) { + private DevBeanInfo createBeanInfo(BeanInfo beanInfo, CompletedApplicationClassPredicateBuildItem predicate) { List qualifiers = new ArrayList<>(); for (AnnotationInstance qualAnnotation : beanInfo.getQualifiers()) { qualifiers.add(new ClassName(qualAnnotation.name().toString())); @@ -118,48 +122,55 @@ private DevBeanInfo createBeanInfo(BeanInfo beanInfo) { Optional target = beanInfo.getTarget(); if (target.isPresent()) { AnnotationTarget annotated = target.get(); - String methodName = null; + DotName name = null; + String memberName = null; ClassName type = null; ClassName providerClass = null; DevBeanKind kind = null; if (annotated.kind() == Kind.METHOD) { MethodInfo method = annotated.asMethod(); - methodName = method.name(); - type = new ClassName(method.returnType().toString()); + memberName = method.name(); + name = method.returnType().name(); + type = new ClassName(name.toString()); providerClass = new ClassName(method.declaringClass().toString()); kind = DevBeanKind.METHOD; } else if (annotated.kind() == Kind.FIELD) { FieldInfo field = annotated.asField(); - methodName = field.name(); - type = new ClassName(field.type().toString()); + memberName = field.name(); + name = field.type().name(); + type = new ClassName(name.toString()); providerClass = new ClassName(field.declaringClass().toString()); kind = DevBeanKind.FIELD; } else if (annotated.kind() == Kind.CLASS) { ClassInfo klass = annotated.asClass(); + name = klass.name(); type = new ClassName(klass.name().toString()); kind = DevBeanKind.CLASS; } - return new DevBeanInfo(providerClass, methodName, type, qualifiers, scope, kind); + return new DevBeanInfo(providerClass, memberName, type, qualifiers, scope, kind, + target.isPresent() ? predicate.test(name) : false); } else { return new DevBeanInfo(null, null, new ClassName(beanInfo.getBeanClass().toString()), qualifiers, - scope, DevBeanKind.SYNTHETIC); + scope, DevBeanKind.SYNTHETIC, false); } } - private DevObserverInfo createDevInfo(ObserverInfo observer) { + private DevObserverInfo createObserverInfo(ObserverInfo observer, CompletedApplicationClassPredicateBuildItem predicate) { List qualifiers = new ArrayList<>(); - ClassName name = null; + ClassName declaringClassName = null; String methodName = null; for (AnnotationInstance qualAnnotation : observer.getQualifiers()) { qualifiers.add(new ClassName(qualAnnotation.name().toString())); } if (observer.getDeclaringBean() != null) { - name = new ClassName(observer.getObserverMethod().declaringClass().name().toString()); + declaringClassName = new ClassName(observer.getObserverMethod().declaringClass().name().toString()); methodName = observer.getObserverMethod().name(); } - return new DevObserverInfo(name, methodName, observer.getObservedType().toString(), qualifiers, observer.getPriority(), - observer.isAsync(), observer.getReception(), observer.getTransactionPhase()); + return new DevObserverInfo(declaringClassName, methodName, observer.getObservedType().toString(), qualifiers, + observer.getPriority(), + observer.isAsync(), observer.getReception(), observer.getTransactionPhase(), + declaringClassName != null ? predicate.test(observer.getObserverMethod().declaringClass().name()) : false); } private boolean isAdditionalBeanDefiningAnnotationOn(ClassInfo beanClass, diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java index 303a8f7af27a99..33bfa9cf09bb66 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/devconsole/DevObserverInfo.java @@ -5,9 +5,12 @@ import javax.enterprise.event.Reception; import javax.enterprise.event.TransactionPhase; +import io.quarkus.deployment.dev.console.ClassName; + public class DevObserverInfo implements Comparable { - private final ClassName name; + private final boolean isApplicationObserver; + private final ClassName declaringClassName; private final String methodName; private final String observedType; private List qualifiers; @@ -16,9 +19,10 @@ public class DevObserverInfo implements Comparable { private final Reception reception; private final TransactionPhase transactionPhase; - public DevObserverInfo(ClassName name, String methodInfo, String observedType, List qualifiers, int priority, - boolean isAsync, Reception reception, TransactionPhase transactionPhase) { - this.name = name; + public DevObserverInfo(ClassName declaringClassName, String methodInfo, String observedType, List qualifiers, + int priority, + boolean isAsync, Reception reception, TransactionPhase transactionPhase, boolean isApplicationObserver) { + this.declaringClassName = declaringClassName; this.methodName = methodInfo; this.observedType = observedType; this.qualifiers = qualifiers; @@ -26,10 +30,11 @@ public DevObserverInfo(ClassName name, String methodInfo, String observedType, L this.isAsync = isAsync; this.reception = reception; this.transactionPhase = transactionPhase; + this.isApplicationObserver = isApplicationObserver; } - public ClassName getName() { - return name; + public ClassName getDeclaringClassName() { + return declaringClassName; } public String getMethodName() { @@ -60,14 +65,22 @@ public TransactionPhase getTransactionPhase() { return transactionPhase; } + public boolean isApplicationObserver() { + return isApplicationObserver; + } + @Override public int compareTo(DevObserverInfo o) { - if (name == null && o.name != null) { - return -1; - } else if (name != null && o.name == null) { - return 1; + // Application beans should go first + if (isApplicationObserver == o.isApplicationObserver) { + if (declaringClassName == null && o.declaringClassName != null) { + return -1; + } else if (declaringClassName != null && o.declaringClassName == null) { + return 1; + } + int ret = declaringClassName.compareTo(o.declaringClassName); + return ret == 0 ? methodName.compareTo(o.methodName) : ret; } - int ret = name.getLocalName().compareTo(o.name.getLocalName()); - return ret == 0 ? methodName.compareTo(o.methodName) : ret; + return isApplicationObserver ? -1 : 1; } } diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/beans.html b/extensions/arc/deployment/src/main/resources/dev-templates/beans.html index 377730bb4c3fc4..7407c1946492a3 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/beans.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/beans.html @@ -2,6 +2,7 @@ {#style} .annotation { color: gray; + font-style: italic; } {/style} {#title}Beans{/title} @@ -11,7 +12,7 @@ # Bean - Source + Kind diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html b/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html index bef53c49c182b6..dd2fe654bde0dc 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/embedded.html @@ -18,8 +18,4 @@ {/if} - Removed Beans {info:arcContainer.removedBeans.size} -
- - - Interceptors {info:arcContainer.interceptors.size} + Removed Beans {info:arcContainer.removedBeans.size} \ No newline at end of file diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/observers.html b/extensions/arc/deployment/src/main/resources/dev-templates/observers.html index 3827d0ab8de4c0..3c7b8ce6b035e7 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/observers.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/observers.html @@ -18,8 +18,8 @@ {count}. - {#if observer.name != null} - {observer.name.localName}.{observer.methodName}() + {#if observer.declaringClassName} + {observer.declaringClassName.shortenedPackageName}.{observer.declaringClassName.localName}.{observer.methodName}() {#else} Synthetic {/if} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html index c62639ff4fcd58..77d0aabdf98248 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/bean-declaration.html @@ -1,10 +1,10 @@ {#switch it.kind} {#case METHOD} - {it.name.localName}.{it.methodName}() + Producer method
{it.declaringClassName.localName}.{it.memberName}() {#case FIELD} - {it.name.localName}.{it.methodName} + Producer field
{it.declaringClassName.localName}.{it.memberName} {#case CLASS} - Class + Class {#else} Synthetic {/switch} \ No newline at end of file diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html index 2c9ae599b4f076..25de035c8bef39 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/display-bean.html @@ -1,7 +1,7 @@ -@{it.scope.localName}
-{#for qual in it.qualifiers} - {#if qual.name != 'javax.inject.Named' && qual.name != 'javax.enterprise.inject.Any' && qual.name != 'javax.enterprise.inject.Default'} - @{qual.localName}
+@{it.scope.localName}
+{#for q in it.qualifiers} + {#if q.name != 'javax.inject.Named' && q.name != 'javax.enterprise.inject.Any' && q.name != 'javax.enterprise.inject.Default'} + @{q.localName}
{/if} {/for} -{it.type.localName} +{it.type.shortenedPackageName}.{it.type.localName} diff --git a/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html b/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html index 1e645c938abef5..6d196e3377cbc3 100644 --- a/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html +++ b/extensions/arc/deployment/src/main/resources/dev-templates/tags/tree.html @@ -3,13 +3,13 @@ {#if next}├─{#else}└─{/if} {/if} {#if it.children} -{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if} +{it.declaringClassPackage}.{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if}
    {#each it.children} {#tree it root=false next=hasNext /} {/each}
{#else} -{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if} +{it.declaringClassPackage}.{it.methodInfo} {#duration it /}{#kind it /}{#if it.message != null} Error{/if} {/if} \ No newline at end of file diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java index e39534089db593..a3fca8952402dd 100644 --- a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/devconsole/Invocation.java @@ -64,6 +64,10 @@ public Method getMethod() { return method; } + public String getDeclaringClassPackage() { + return shorten(getPackageName(method.getDeclaringClass().getName())); + } + public String getMethodInfo() { return method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()"; } @@ -85,6 +89,28 @@ public String toString() { return kind + " invocation of " + method; } + public String getPackageName(String name) { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) { + return name.substring(0, lastDot); + } + return ""; + } + + private String shorten(String value) { + String[] parts = value.split("\\."); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < parts.length; i++) { + if (i == parts.length - 1) { + builder.append(parts[i]); + } else { + builder.append(parts[i].charAt(0)); + builder.append('.'); + } + } + return builder.toString(); + } + public enum Kind { BUSINESS, 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 ba8f7787d573c6..7737183d5d09ca 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 @@ -36,6 +36,7 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; +import io.netty.handler.codec.http.HttpHeaderNames; import io.quarkus.bootstrap.classloading.QuarkusClassLoader; import io.quarkus.bootstrap.model.AppArtifact; import io.quarkus.builder.item.SimpleBuildItem; @@ -68,14 +69,18 @@ import io.quarkus.qute.NamespaceResolver; import io.quarkus.qute.RawString; import io.quarkus.qute.ReflectionValueResolver; +import io.quarkus.qute.ResultMapper; import io.quarkus.qute.Results; import io.quarkus.qute.Results.Result; +import io.quarkus.qute.TemplateException; import io.quarkus.qute.TemplateLocator; +import io.quarkus.qute.TemplateNode.Origin; import io.quarkus.qute.UserTagSectionHelper; import io.quarkus.qute.ValueResolver; import io.quarkus.qute.ValueResolvers; import io.quarkus.qute.Variant; import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.TemplateHtmlBuilder; import io.quarkus.vertx.http.deployment.HttpRootPathBuildItem; import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; @@ -198,7 +203,11 @@ protected static void newRouter(Engine engine, Handler errorHandler = new Handler() { @Override public void handle(RoutingContext event) { - log.error("Dev console request failed ", event.failure()); + String message = "Dev console request failed"; + log.error(message, event.failure()); + event.response().headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8"); + event.response().end( + new TemplateHtmlBuilder("Internal Server Error", message, message).stack(event.failure()).toString()); } }; router = Router.router(devConsoleVertx); @@ -398,6 +407,28 @@ private Engine buildEngine(List devTemplatePaths) { } builder.addLocator(id -> locateTemplate(id, templates)); + builder.addResultMapper(new ResultMapper() { + @Override + public int getPriority() { + // The priority must be higher than the one used for HtmlEscaper + return 10; + } + + @Override + public boolean appliesTo(Origin origin, Object result) { + return result.equals(Result.NOT_FOUND); + } + + @Override + public String map(Object result, Expression expression) { + Origin origin = expression.getOrigin(); + throw new TemplateException(origin, + String.format("Property not found in expression {%s} in template %s on line %s", + expression.toOriginalString(), + origin.getTemplateId(), origin.getLine())); + } + }); + Engine engine = builder.build(); // pre-load all templates diff --git a/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css b/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css index d3a5913dc3c227..776b92a3101096 100644 --- a/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css +++ b/extensions/vertx-http/deployment/src/main/resources/dev-static/css/dev-console.css @@ -55,3 +55,7 @@ h1 { margin-bottom: 0.75em; } + +.package-name { + color: dimgray; +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/devconsole/ClassNameTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/devconsole/ClassNameTest.java new file mode 100644 index 00000000000000..69eee659913966 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/devconsole/ClassNameTest.java @@ -0,0 +1,27 @@ +package io.quarkus.vertx.http.devconsole; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import io.quarkus.deployment.dev.console.ClassName; + +public class ClassNameTest { + + @Test + public void testShortenedName() { + assertEquals("i.q.d.Foo", new ClassName("io.quarkus.dummy.Foo").getShortenedName()); + assertEquals("c.q.d.B", new ClassName("com.q.dummy.B").getShortenedName()); + assertEquals("Simple", new ClassName("Simple").getShortenedName()); + assertEquals("o.a.Foo$Bar", new ClassName("org.acme.Foo$Bar").getShortenedName()); + } + + @Test + public void testPackageShortenedName() { + assertEquals("i.q.dummy", new ClassName("io.quarkus.dummy.Foo").getShortenedPackageName()); + assertEquals("c.q.dummy", new ClassName("com.q.dummy.B").getShortenedPackageName()); + assertEquals("", new ClassName("Simple").getShortenedPackageName()); + assertEquals("o.acme", new ClassName("org.acme.Foo$Bar").getShortenedPackageName()); + } + +} diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java index 30d4a758032629..3ce950d7bbb12e 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanProcessor.java @@ -232,6 +232,10 @@ public BeanDeployment getBeanDeployment() { public AnnotationLiteralProcessor getAnnotationLiteralProcessor() { return annotationLiterals; } + + public Predicate getApplicationClassPredicate() { + return applicationClassPredicate; + } public BeanDeployment process() throws IOException { Consumer unsupportedBytecodeTransformer = new Consumer() {