Skip to content

Commit

Permalink
Probe bean detail - various fixes and improvements
Browse files Browse the repository at this point in the history
- do not include delegate injection points in dependency graph
- show associated decorators
- show beans a decorator is associated to
- show class-level interceptor bindings
- don't render dependeny graph if there are no data
  • Loading branch information
mkouba authored and jharting committed Aug 18, 2015
1 parent ae9b772 commit 9514e60
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 10 deletions.
1 change: 1 addition & 0 deletions probe/core/src/main/client/app.js
Expand Up @@ -215,6 +215,7 @@ Probe.BeanDetailRoute = Ember.Route.extend(Probe.ResetScroll, {
function(data) {
data.bda = findBeanDeploymentArchive(appController.get('bdas'),
data['bdaId']);
data.showDependencyGraph = data.dependencies || data.dependents;
return data;
}).fail(function(jqXHR, textStatus, errorThrown) {
alert('Unable to get JSON data: ' + textStatus);
Expand Down
42 changes: 39 additions & 3 deletions probe/core/src/main/client/probe.html
Expand Up @@ -170,7 +170,7 @@ <h1>Overview Graph</h1>
data-template-name="beanArchive">

<div class="breadcrumbs">
<i class="fa fa-lg fa-home"></i> / {{#link-to 'beanArchives'}}Bean Archives{{/link-to}} / {{#link-to 'beanArchive' id class='nav-link'}}Bean Archive{{/link-to}}
<i class="fa fa-lg fa-home"></i> / {{#link-to 'beanArchives'}}Bean Archives{{/link-to}} / {{#link-to 'beanArchive' id class='nav-link'}}Bean Archive {{idx}}{{/link-to}}
</div>

<h1>Bean Archive</h1>
Expand Down Expand Up @@ -385,7 +385,7 @@ <h1>Beans</h1>
data-template-name="beanDetail">

<div class="breadcrumbs">
<i class="fa fa-lg fa-home"></i> / {{#link-to 'beanList'}}Beans{{/link-to}} / {{#link-to 'beanDetail' id}}Bean Detail{{/link-to}}
<i class="fa fa-lg fa-home"></i> / {{#link-to 'beanList'}}Beans{{/link-to}} / {{#link-to 'beanDetail' id}}{{abbr beanClass 30 suppressHtml=true}}{{/link-to}}
</div>

<h1>Bean Detail</h1>
Expand Down Expand Up @@ -611,10 +611,43 @@ <h1>Bean Detail</h1>
</div>
</div>
{{/if}}
{{#if classInterceptorBindings}}
<div class="form-group">
<label class="col-sm-2 control-label">Class-level Interceptor Bindings:</label>
<div class="col-sm-10">
{{#each classInterceptorBindings}}
<p class="form-control-static">
{{#if probeComponent}}<span class='probe-comp'>{{value}}</span> {{probe-comp}}{{else}}{{value}}{{/if}}
</p>
{{/each}}
</div>
</div>
{{/if}}
{{#if decorators}}
<div class="form-group">
<label class="col-sm-2 control-label">Associated Decorators:</label>
<div class="col-sm-10">
{{#each decorators}}
<p class="form-control-static"><span class="{{unbound kind}} boxed">{{kind}}</span> {{detail-icon}} {{#link-to 'beanDetail' id}}{{beanClass}}{{/link-to}}</p>
{{/each}}
</div>
</div>
{{/if}}
{{#if associatedTo}}
<div class="form-group">
<label class="col-sm-2 control-label">Associated To:</label>
<div class="col-sm-10">
{{#each associatedTo}}
<p class="form-control-static"><span class="{{unbound kind}} boxed">{{kind}}</span> {{detail-icon}} {{#link-to 'beanDetail' id}}{{beanClass}}{{/link-to}}</p>
{{/each}}
</div>
</div>
{{/if}}
</form>
</div>
</div>

{{#if showDependencyGraph}}
<h2>Dependency Graph</h2>
<div>
<label>
Expand Down Expand Up @@ -653,6 +686,9 @@ <h4 class="modal-title" id="ipInfoModalTitle">Injection Points Info</h4>
</div>
</div>
</div>
{{else}}
<div class="alert alert-info" role="alert"><strong>Dependency graph not built!</strong> This component has neither dependencies nor dependents.</div>
{{/if}}

</script>

Expand Down Expand Up @@ -761,7 +797,7 @@ <h1>Observer Methods</h1>
data-template-name="observerDetail">

<div class="breadcrumbs">
<i class="fa fa-lg fa-home"></i> / Events / {{#link-to 'observerList'}}Observer Methods{{/link-to}} / {{#link-to 'observerDetail' id}}Observer Method Detail{{/link-to}}
<i class="fa fa-lg fa-home"></i> / Events / {{#link-to 'observerList'}}Observer Methods{{/link-to}} / {{#link-to 'observerDetail' id}}{{at}}Observes {{abbr observedType 30 suppressHtml=true}}{{/link-to}}
</div>

<h1>Observer Method Detail</h1>
Expand Down
42 changes: 39 additions & 3 deletions probe/core/src/main/java/org/jboss/weld/probe/Components.java
Expand Up @@ -85,6 +85,17 @@ public int compare(Class<?> o1, Class<?> o2) {
}
};

static final Comparator<Annotation> PROBE_COMPONENT_ANNOTATION_COMPARATOR = new Comparator<Annotation>() {

@Override
public int compare(Annotation o1,Annotation o2) {
// Probe components should have the lowest priority when sorting
int result = Boolean.compare(isProbeAnnotation(o1), isProbeAnnotation(o2));
// Unless decided compare the class names lexicographically
return result == 0 ? o1.annotationType().getName().compareTo(o2.annotationType().getName()) : result;
}
};

private Components() {
}

Expand Down Expand Up @@ -156,19 +167,20 @@ static Set<Dependency> getDependents(Bean<?> bean, Probe probe) {
Set<InjectionPoint> injectionPoints = candidate.getInjectionPoints();
if (injectionPoints != null && !injectionPoints.isEmpty()) {
for (InjectionPoint injectionPoint : injectionPoints) {

if (injectionPoint.isDelegate()) {
// Do not include delegate injection points
continue;
}
// At this point unsatisfied or ambiguous dependency should not exits
Bean<?> candidateDependency = beanManager.resolve(beanManager.getBeans(injectionPoint.getType(),
injectionPoint.getQualifiers().toArray(new Annotation[injectionPoint.getQualifiers().size()])));

if (candidateDependency.getBeanClass().equals(InstanceImpl.class)) {
Bean<?> lazilyFetched = getInstanceResolvedBean(beanManager, injectionPoint);
if (lazilyFetched != null && lazilyFetched.equals(bean)) {
dependents.add(new Dependency(candidate, injectionPoint, INFO_FETCHING_LAZILY, true));
continue;
}
}

boolean satisfies = false;
if (isBuiltinBeanButNotExtension(candidateDependency)) {
satisfies = bean.equals(probe.getBean(Components.getBuiltinBeanId((AbstractBuiltInBean<?>) candidateDependency)));
Expand Down Expand Up @@ -196,6 +208,10 @@ static Set<Dependency> getDependencies(Bean<?> bean, BeanManager beanManager, Pr
Set<InjectionPoint> injectionPoints = bean.getInjectionPoints();
if (injectionPoints != null && !injectionPoints.isEmpty()) {
for (InjectionPoint injectionPoint : injectionPoints) {
if (injectionPoint.isDelegate()) {
// Do not include delegate injection points
continue;
}
// At this point unsatisfied or ambiguous dependency should not exits
Bean<?> dependency = beanManager.resolve(beanManager.getBeans(injectionPoint.getType(),
injectionPoint.getQualifiers().toArray(new Annotation[injectionPoint.getQualifiers().size()])));
Expand Down Expand Up @@ -301,6 +317,15 @@ static boolean isProbeComponent(Class<?> clazz) {
return clazz.getName().startsWith(Probe.class.getPackage().getName());
}

/**
*
* @param annotation
* @return <code>true</code> if the given annotation is a probe annotation, <code>false</code> otherwise
*/
static boolean isProbeAnnotation(Annotation annotation) {
return isProbeComponent(annotation.annotationType());
}

/**
*
* @param candidates
Expand All @@ -312,6 +337,17 @@ static <T> List<Class<? extends T>> getSortedProbeComponetCandidates(Collection<
return result;
}

/**
*
* @param candidates
* @return the sorted list of annotations, where the probe component annotations have the lowest priority
*/
static <T> List<Annotation> getSortedProbeComponetAnnotationCandidates(Collection<Annotation> candidates) {
List<Annotation> result = new ArrayList<Annotation>(candidates);
Collections.sort(result, Components.PROBE_COMPONENT_ANNOTATION_COMPARATOR);
return result;
}

/**
*
* @author Martin Kouba
Expand Down
62 changes: 58 additions & 4 deletions probe/core/src/main/java/org/jboss/weld/probe/JsonObjects.java
Expand Up @@ -20,6 +20,7 @@
import static org.jboss.weld.probe.Strings.ALTERNATIVES;
import static org.jboss.weld.probe.Strings.ANNOTATED_METHOD;
import static org.jboss.weld.probe.Strings.APPLICATION;
import static org.jboss.weld.probe.Strings.ASSOCIATED_TO;
import static org.jboss.weld.probe.Strings.AS_STRING;
import static org.jboss.weld.probe.Strings.BDAS;
import static org.jboss.weld.probe.Strings.BDA_ID;
Expand All @@ -30,6 +31,7 @@
import static org.jboss.weld.probe.Strings.CHILDREN;
import static org.jboss.weld.probe.Strings.CIDS;
import static org.jboss.weld.probe.Strings.CLASS;
import static org.jboss.weld.probe.Strings.CLASS_INTERCEPTOR_BINDINGS;
import static org.jboss.weld.probe.Strings.CONFIGURATION;
import static org.jboss.weld.probe.Strings.CONTAINER;
import static org.jboss.weld.probe.Strings.CONTEXTS;
Expand Down Expand Up @@ -123,6 +125,7 @@
import javax.servlet.http.HttpSession;

import org.jboss.weld.Container;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bean.AbstractProducerBean;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.builtin.AbstractBuiltInBean;
Expand All @@ -140,6 +143,7 @@
import org.jboss.weld.event.ObserverMethodImpl;
import org.jboss.weld.injection.producer.ProducerFieldProducer;
import org.jboss.weld.injection.producer.ProducerMethodProducer;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.probe.Components.BeanKind;
import org.jboss.weld.probe.Components.Dependency;
Expand Down Expand Up @@ -263,8 +267,8 @@ public int compare(ConfigurationKey o1, ConfigurationKey o2) {
// Unsupported property type
continue;
}
configBuilder.add(Json.objectBuilder().add(NAME, key.get()).add(DEFAULT_VALUE, defaultValue.toString()).add(VALUE, value.toString())
.add(DESCRIPTION, desc));
configBuilder.add(
Json.objectBuilder().add(NAME, key.get()).add(DEFAULT_VALUE, defaultValue.toString()).add(VALUE, value.toString()).add(DESCRIPTION, desc));
}
deploymentBuilder.add(CONFIGURATION, configBuilder);

Expand Down Expand Up @@ -488,11 +492,61 @@ static String createFullBeanJson(Bean<?> bean, boolean transientDependencies, bo
decoratedTypes.add(Formats.formatType(type, false));
}
beanBuilder.add(DECORATED_TYPES, decoratedTypes);
// ASSOCIATED TO BEANS
Set<Bean<?>> decoratedBeans = findDecoratedBeans(decorator, beanManager, probe);
if (!decoratedBeans.isEmpty()) {
JsonArrayBuilder decoratedBeansBuilder = Json.arrayBuilder();
for (Bean<?> decoratedBean : decoratedBeans) {
decoratedBeansBuilder.add(createSimpleBeanJson(decoratedBean, probe));
}
beanBuilder.add(ASSOCIATED_TO, decoratedBeansBuilder);
}
}

if (bean instanceof AbstractClassBean) {
AbstractClassBean<?> abstractClassBean = (AbstractClassBean<?>) bean;
InterceptionModel interceptionModel = abstractClassBean.getInterceptors();
// CLASS-LEVEL BINDINGS
if (interceptionModel != null) {
Set<Annotation> classInterceptorBindings = interceptionModel.getClassInterceptorBindings();
if (!classInterceptorBindings.isEmpty()) {
JsonArrayBuilder bindingsBuilder = Json.arrayBuilder();
for (Annotation binding : Components.getSortedProbeComponetAnnotationCandidates(classInterceptorBindings)) {
bindingsBuilder.add(Json.objectBuilder().add(VALUE, binding.toString()).add(PROBE_COMPONENT, Components.isProbeAnnotation(binding)));
}
beanBuilder.add(CLASS_INTERCEPTOR_BINDINGS, bindingsBuilder);
}
}
// ASSOCIATED DECORATORS
List<Decorator<?>> decorators = abstractClassBean.getDecorators();
if (!decorators.isEmpty()) {
JsonArrayBuilder decoratorsBuilder = Json.arrayBuilder();
for (Decorator<?> decorator : decorators) {
decoratorsBuilder.add(createSimpleBeanJson(decorator, probe));
}
beanBuilder.add(DECORATORS, decoratorsBuilder);
}
}

return beanBuilder.build();
}

private static Set<Bean<?>> findDecoratedBeans(Decorator<?> decorator, BeanManagerImpl beanManager, Probe probe) {
Set<Bean<?>> beans = new HashSet<Bean<?>>();
for (Bean<?> bean : probe.getBeans()) {
List<?> decorators;
if (bean instanceof AbstractClassBean) {
decorators = ((AbstractClassBean<?>) bean).getDecorators();
} else {
decorators = beanManager.resolveDecorators(bean.getTypes(), bean.getQualifiers());
}
if (decorators.contains(decorator)) {
beans.add(bean);
}
}
return beans;
}

private static boolean isSelectedAlternative(ModuleEnablement enablement, Bean<?> bean) {
if (bean.isAlternative()) {
if (enablement.isEnabledAlternativeClass(bean.getBeanClass())) {
Expand Down Expand Up @@ -648,8 +702,8 @@ static JsonArrayBuilder createDependents(Bean<?> parent, Bean<?> bean, Probe pro
for (Dependency dependent : Components.getDependents(bean, probe)) {
// Workaround for built-in beans - these are identified by the set of types
if (Components.isBuiltinBeanButNotExtension(dependent.getBean())) {
dependentsBuilder.add(createDependency(probe.getBean(Components.getBuiltinBeanId((AbstractBuiltInBean<?>) dependent.getBean())), dependent,
probe));
dependentsBuilder
.add(createDependency(probe.getBean(Components.getBuiltinBeanId((AbstractBuiltInBean<?>) dependent.getBean())), dependent, probe));
continue;
}
// Handle circular dependencies
Expand Down
2 changes: 2 additions & 0 deletions probe/core/src/main/java/org/jboss/weld/probe/Strings.java
Expand Up @@ -97,6 +97,8 @@ public final class Strings {
public static final String DELEGATE_TYPE = "delegateType";
public static final String DELEGATE_QUALIFIERS = "delegateQualifiers";
public static final String DECORATED_TYPES = "decoratedTypes";
public static final String CLASS_INTERCEPTOR_BINDINGS = "classInterceptorBindings";
public static final String ASSOCIATED_TO = "associatedTo";

public static final String PAGE = "page";
public static final String PAGE_SIZE = "pageSize";
Expand Down

0 comments on commit 9514e60

Please sign in to comment.