Skip to content

Commit

Permalink
Merge pull request #29775 from mkouba/check-normalscoped-synthetic-beans
Browse files Browse the repository at this point in the history
Throw a CreationException if a normal scoped synthetic bean creates null
  • Loading branch information
manovotn committed Dec 9, 2022
2 parents 213cbde + 84d1e23 commit 10fa7eb
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
Expand Up @@ -27,6 +27,7 @@

import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.CreationException;
import javax.enterprise.inject.IllegalProductException;
import javax.enterprise.inject.literal.InjectLiteral;
import javax.enterprise.inject.spi.InterceptionType;
Expand Down Expand Up @@ -63,6 +64,8 @@
import io.quarkus.gizmo.FieldCreator;
import io.quarkus.gizmo.FieldDescriptor;
import io.quarkus.gizmo.FunctionCreator;
import io.quarkus.gizmo.Gizmo;
import io.quarkus.gizmo.Gizmo.StringBuilderGenerator;
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
Expand Down Expand Up @@ -946,7 +949,25 @@ protected void implementCreate(ClassOutput classOutput, ClassCreator beanCreator
injectionPointToProviderSupplierField, reflectionRegistration,
targetPackage, isApplicationClass, create);
} else if (bean.isSynthetic()) {
bean.getCreatorConsumer().accept(create);
if (bean.getScope().isNormal()) {
// Normal scoped synthetic beans should never return null
MethodCreator createSynthetic = beanCreator
.getMethodCreator("createSynthetic", providerType.descriptorName(), CreationalContext.class)
.setModifiers(ACC_PRIVATE);
bean.getCreatorConsumer().accept(createSynthetic);
ResultHandle ret = create.invokeVirtualMethod(createSynthetic.getMethodDescriptor(), create.getThis(),
create.getMethodParam(0));
BytecodeCreator nullBeanInstance = create.ifNull(ret).trueBranch();
StringBuilderGenerator message = Gizmo.newStringBuilder(nullBeanInstance);
message.append("Null contextual instance was produced by a normal scoped synthetic bean: ");
message.append(Gizmo.toString(nullBeanInstance, nullBeanInstance.getThis()));
ResultHandle e = nullBeanInstance.newInstance(
MethodDescriptor.ofConstructor(CreationException.class, String.class), message.callToString());
nullBeanInstance.throwException(e);
create.returnValue(ret);
} else {
bean.getCreatorConsumer().accept(create);
}
}

// Bridge method needed
Expand Down
@@ -0,0 +1,55 @@
package io.quarkus.arc.test.buildextension.beans;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Map;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.CreationException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.arc.Arc;
import io.quarkus.arc.BeanCreator;
import io.quarkus.arc.processor.BeanRegistrar;
import io.quarkus.arc.test.ArcTestContainer;

public class NormalScopedSyntheticBeanProducedNullTest {

public static volatile boolean beanDestroyerInvoked = false;

@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder().beanRegistrars(new TestRegistrar()).build();

@Test
public void testCreationException() {
CreationException e = assertThrows(CreationException.class, () -> {
Arc.container().instance(CharSequence.class).get().length();
});
assertTrue(e.getMessage().contains("Null contextual instance was produced by a normal scoped synthetic bean"),
e.getMessage());
}

static class TestRegistrar implements BeanRegistrar {

@Override
public void register(RegistrationContext context) {
context.configure(CharSequence.class).types(CharSequence.class).unremovable().scope(ApplicationScoped.class)
.creator(CharSequenceCreator.class).done();
}

}

public static class CharSequenceCreator implements BeanCreator<CharSequence> {

@Override
public CharSequence create(CreationalContext<CharSequence> creationalContext, Map<String, Object> params) {
return null;
}

}

}

0 comments on commit 10fa7eb

Please sign in to comment.