Skip to content

Commit

Permalink
Merge pull request #25552 from mkouba/arc-client-proxies-context-not-…
Browse files Browse the repository at this point in the history
…active

ArC - improved message for some occurrences of ContextNotActiveException
  • Loading branch information
geoand authored May 13, 2022
2 parents 48f5aae + 801e519 commit 65175c1
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ Collection<Resource> generateSyntheticBean(BeanInfo bean) {
implementGetKind(beanCreator, InjectableBean.Kind.SYNTHETIC);
implementEquals(bean, beanCreator);
implementHashCode(bean, beanCreator);
implementToString(beanCreator);

beanCreator.close();
return classOutput.getResources();
Expand Down Expand Up @@ -342,6 +343,7 @@ Collection<Resource> generateClassBean(BeanInfo bean, ClassInfo beanClass) {
implementIsSuppressed(bean, beanCreator);
implementEquals(bean, beanCreator);
implementHashCode(bean, beanCreator);
implementToString(beanCreator);

beanCreator.close();
return classOutput.getResources();
Expand Down Expand Up @@ -445,6 +447,7 @@ Collection<Resource> generateProducerMethodBean(BeanInfo bean, MethodInfo produc
implementIsSuppressed(bean, beanCreator);
implementEquals(bean, beanCreator);
implementHashCode(bean, beanCreator);
implementToString(beanCreator);

beanCreator.close();
return classOutput.getResources();
Expand Down Expand Up @@ -533,6 +536,7 @@ Collection<Resource> generateProducerFieldBean(BeanInfo bean, FieldInfo producer
implementIsSuppressed(bean, beanCreator);
implementEquals(bean, beanCreator);
implementHashCode(bean, beanCreator);
implementToString(beanCreator);

beanCreator.close();
return classOutput.getResources();
Expand Down Expand Up @@ -1697,6 +1701,11 @@ protected void implementHashCode(BeanInfo bean, ClassCreator beanCreator) {
hashCode.returnValue(constantHashCodeResult);
}

protected void implementToString(ClassCreator beanCreator) {
MethodCreator toString = beanCreator.getMethodCreator("toString", String.class).setModifiers(ACC_PUBLIC);
toString.returnValue(toString.invokeStaticMethod(MethodDescriptors.BEANS_TO_STRING, toString.getThis()));
}

/**
*
* @param bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ public final class MethodDescriptors {
ComponentsProvider.class, "unableToLoadRemovedBeanType",
void.class, String.class, Throwable.class);

public static final MethodDescriptor BEANS_TO_STRING = MethodDescriptor.ofMethod(io.quarkus.arc.impl.Beans.class,
"toString", String.class,
InjectableBean.class);

private MethodDescriptors() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ enum Kind {
PRODUCER_METHOD,
SYNTHETIC,
INTERCEPTOR,
DECORATOR;
DECORATOR,
BUILTIN,
;

public static Kind from(String value) {
for (Kind kind : values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ public ArcContainerImpl(CurrentContextFactory currentContextFactory) {
applicationContext = new ApplicationContext();
singletonContext = new SingletonContext();
requestContext = new RequestContext(this.currentContextFactory.create(RequestScoped.class));
contexts = new HashMap<>();
putContext(requestContext);
putContext(applicationContext);
putContext(singletonContext);
Map<Class<? extends Annotation>, List<InjectableContext>> contexts = new HashMap<>();
putContext(requestContext, contexts);
putContext(applicationContext, contexts);
putContext(singletonContext, contexts);

for (ComponentsProvider componentsProvider : ServiceLoader.load(ComponentsProvider.class)) {
Components components = componentsProvider.getComponents();
Expand All @@ -143,11 +143,14 @@ public ArcContainerImpl(CurrentContextFactory currentContextFactory) {
throw new IllegalStateException(
"Failed to register a context - built-in singleton context is always active: " + context);
}
putContext(context);
putContext(context, contexts);
}
transitiveInterceptorBindings.putAll(components.getTransitiveInterceptorBindings());
qualifierNonbindingMembers.putAll(components.getQualifierNonbindingMembers());
}

this.contexts = Map.copyOf(contexts);

// register built-in beans
addBuiltInBeans(beans);

Expand All @@ -173,15 +176,15 @@ public ArcContainerImpl(CurrentContextFactory currentContextFactory) {
this.qualifierNonbindingMembers = Map.copyOf(qualifierNonbindingMembers);
}

private void putContext(InjectableContext context) {
private void putContext(InjectableContext context, Map<Class<? extends Annotation>, List<InjectableContext>> contexts) {
Collection<InjectableContext> values = contexts.get(context.getScope());
if (values == null) {
contexts.put(context.getScope(), Collections.singletonList(context));
} else {
List<InjectableContext> multi = new ArrayList<>(values.size() + 1);
multi.addAll(values);
multi.add(context);
contexts.put(context.getScope(), Collections.unmodifiableList(multi));
contexts.put(context.getScope(), List.copyOf(multi));
}
}

Expand Down Expand Up @@ -407,7 +410,6 @@ public synchronized void shutdown() {

// Clear caches
Reflections.clearCaches();
contexts.clear();
resolved.clear();
running.set(false);
InterceptedStaticMethods.clear();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.quarkus.arc.impl;

import io.quarkus.arc.InjectableBean;

public class Beans {

private Beans() {
}

public static String toString(InjectableBean<?> bean) {
return new StringBuilder()
.append(bean.getKind())
.append(" bean [class=")
.append(bean.getBeanClass().getName())
.append(", id=")
.append(bean.getIdentifier())
.append("]")
.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ public String getIdentifier() {
public T create(CreationalContext<T> creationalContext) {
return get(creationalContext);
}

@Override
public Kind getKind() {
return Kind.BUILTIN;
}

@Override
public String toString() {
return Beans.toString(this);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.quarkus.arc.InjectableContext;
import java.util.List;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.spi.Contextual;

public final class ClientProxies {
Expand Down Expand Up @@ -43,7 +44,13 @@ public static <T> T getDelegate(InjectableBean<T> bean) {
}
}
if (result == null) {
throw new ContextNotActiveException();
String msg = String.format(
"%s context was not active when trying to obtain a bean instance for a client proxy of %s",
bean.getScope().getSimpleName(), bean);
if (bean.getScope().equals(RequestScoped.class)) {
msg += "\n\t- you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding";
}
throw new ContextNotActiveException(msg);
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContex
T result = getIfActive(contextual,
CreationalContextImpl.unwrap(Objects.requireNonNull(creationalContext, "CreationalContext must not be null")));
if (result == null) {
throw new ContextNotActiveException();
throw notActive();
}
return result;
}
Expand All @@ -96,7 +96,7 @@ public <T> T get(Contextual<T> contextual) {
}
RequestContextState state = currentContext.get();
if (state == null) {
throw new ContextNotActiveException();
throw notActive();
}
ContextInstanceHandle<T> instance = (ContextInstanceHandle<T>) state.map.get(contextual);
return instance == null ? null : instance.get();
Expand All @@ -112,7 +112,7 @@ public void destroy(Contextual<?> contextual) {
RequestContextState state = currentContext.get();
if (state == null) {
// Context is not active
throw new ContextNotActiveException();
throw notActive();
}
ContextInstanceHandle<?> instance = state.map.remove(contextual);
if (instance != null) {
Expand Down Expand Up @@ -140,7 +140,7 @@ public ContextState getState() {
RequestContextState state = currentContext.get();
if (state == null) {
// Thread local not set - context is not active!
throw new ContextNotActiveException();
throw notActive();
}
return state;
}
Expand Down Expand Up @@ -206,6 +206,11 @@ private void fireIfNotEmpty(LazyValue<Notifier<Object>> value) {
}
}

private ContextNotActiveException notActive() {
String msg = "Request context is not active - you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding";
return new ContextNotActiveException(msg);
}

private static Notifier<Object> createInitializedNotifier() {
return EventImpl.createNotifier(Object.class, Object.class,
new HashSet<>(Arrays.asList(Initialized.Literal.REQUEST, Any.Literal.INSTANCE)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.arc.test.clientproxy.contextnotactive;

import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

import io.quarkus.arc.Arc;
import io.quarkus.arc.test.ArcTestContainer;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.RequestScoped;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class ClientProxyContextNotActiveTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(RequestFoo.class);

@Test
public void testToStringIsDelegated() {
RequestFoo foo = Arc.container().instance(RequestFoo.class).get();
assertThatExceptionOfType(ContextNotActiveException.class).isThrownBy(() -> foo.ping())
.withMessageContaining(
"RequestScoped context was not active when trying to obtain a bean instance for a client proxy of CLASS bean [class=io.quarkus.arc.test.clientproxy.contextnotactive.ClientProxyContextNotActiveTest$RequestFoo, id=3e5a77b35b0824bc957993f6db95a37e766e929e]")
.withMessageContaining(
"you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding");
}

@RequestScoped
static class RequestFoo {

void ping() {
}

}
}

0 comments on commit 65175c1

Please sign in to comment.