0

I come across a strange behavior. I looked for a possible explanation but I did not find (always the same types of answers).

My implementation is perfectly deployed under WildFly 10.x and the Logger works perfectly. I created very classic elements of CDI encapsulation of a Logger production bean. As shown it works well in deployed mode. I deleted the logging subsystem provided by Wildfly to use as logback and the configuration contained in the war file.

The worry is during a unit test. It tells me that the injected logger is null. It seems to me both normal but odd.

The CDI Logger Producer:

public class LoggerProducer {

    @Produces
    public Logger createLogger(InjectionPoint injectionPoint) {
        return LoggerFactory.getLogger(injectionPoint.getBean().getBeanClass());
    }

}

The implementation of a specific interceptor :

@Interceptor
@RestOperation
public class RestOperationInterceptor {

    @Inject
    private Logger logger;

    @AroundInvoke
    public Object interceptRestOperation(InvocationContext context) throws Exception {
        Preconditions.checkNotNull(context);
        logger.info("Context parameters : {}", MoreObjects.toStringHelper(context.getParameters()).toString());
        return context.proceed();
    }

}

This code works well on my Wildfly Server. The bean discovery (beans.xml), only for this interceptor and to avoid @Dependent annotation on LoggerProducer.class :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"
       bean-discovery-mode="all">

    <interceptors>
        <class>fr.hoag.interceptors.RestOperationInterceptor</class>
    </interceptors>

</beans>

But this unit test...

@RunWith(CdiRunner.class)
public class RestInterceptorTest {

    @Produces /* @Mock/@Inject etc. */
    Logger logger;

    @Test
    public void should_intercept_rest_request() throws Exception {
        InvocationContext context = mock(InvocationContext.class);
        when(context.getParameters()).thenReturn(new Object[]{1,2,3});
        when(context.proceed()).thenReturn("test");
        RestOperationInterceptor interceptor = new RestOperationInterceptor();
        assertThat(interceptor.interceptRestOperation(context)).isEqualTo("test");
    }

}

The result is (Line 27 of RestOperationInterceptor is about the logger, context and context.getParameters() are not null):

java.lang.NullPointerException
    at fr.hoag.interceptors.RestOperationInterceptor.interceptRestOperation(RestOperationInterceptor.java:27)
    at RestInterceptorTest.should_intercept_rest_request(RestInterceptorTest.java:34)
    at org.jboss.weld.proxies.RestInterceptorTest$Proxy$_$$_WeldClientProxy.should_intercept_rest_request(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.jglue.cdiunit.CdiRunner$2.evaluate(CdiRunner.java:179)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

The WELD stacktrace : Logger seems to be well produced.

11:18:38.388 [main] DEBUG org.jboss.weld.Bootstrap - WELD-000106: Bean: Producer Field [Logger] with qualifiers [@Any @Default] declared as [[UnbackedAnnotatedField] @Produces RestInterceptorTest.logger]

I think something is missing in bean discovery for the LoggerProducer in CDIUnit. What could i forget ?

Thanks you in advance.

default locale
  • 13,035
  • 13
  • 56
  • 62
nletteron
  • 25
  • 5
  • 1
    Your problem is this : `RestOperationInterceptor interceptor = new RestOperationInterceptor();` => no new with CDI! – Rouliboy Jan 25 '17 at 10:43
  • @Rouliboy Thanks for your answer. 1- If i inject RestOperationInterceptor and i suppress instantiation in JUnit test, i have an "Unsatisfied Dependency" error on RestOperationInterceptor. (the Wildfly container load it with beans.xml, but i don't know how Interceptor annoted classes could be correctly injected. For me, i don't want to add a Dependent annotation on LoggerProducer). 2- Using InjectMock ou Mock => same mistake : logger null. – nletteron Jan 25 '17 at 13:12
  • I tested on my side, and it looks like it's not possible to @Inject an interceptor during Unit test (I still didn't understood why). So the best way to solve your problem is to create a new interceptor as you did, and to mock the logger using Whitebox from Powermock. – Rouliboy Jan 25 '17 at 14:06
  • Yes. I have tested too. I have a specific error : org.jboss.weld.exceptions.DeploymentException: WELD-001417: Enabled interceptor class fr.hoag.interceptors.RestOperationInterceptor (fr.hoag.interceptors.RestOperationInterceptor) does not match an interceptor bean: the class is not found, or not annotated with Interceptor and still not registered through a portable extension, or not annotated with Dependent inside an implicit bean archive . Interresting. (Same with injection by constructor or directly using new in Junit case). I will test with PowerMock. – nletteron Jan 25 '17 at 14:13

0 Answers0