This one is puzzling me. I created a minimal JAX-RS application based on JavaEE7 running on Wildfly 10.1.
@ApplicationPath("")
public class JAXRSConfiguration extends Application {
@Override
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(Arrays.asList(Resource.class));
}
}
The resource injects a single dummy stateless bean:
@Path("")
public class Resource {
@Inject
Manager manager;
@GET
@Path("/go")
public void go() {
manager.call();
}
}
This is the bean:
@Stateless
public class Manager {
@PostConstruct
private void init() {
System.out.println("POST CONSTRUCT ");
}
void call() {
System.out.println("called ");
}
}
Using the browser to execute the GET causes the following error:
org.jboss.resteasy.spi.UnhandledException: org.jboss.weld.exceptions.WeldException: Class org.jboss.weld.util.reflection.Reflections can not access a member of class com.a.b.Manager with modifiers ""
Can post full stack trace but all the Caused By messages are the same.
I searched for this error and it happens when the injected bean is not public, but mine is. I decided to try to remove the public to see what it will complain about and... it works. The bean is injected, any injections it might have are injected, the post construct method is called and all the prints are printed.
This is in complete contrast to Does ejb stateless class has to be public?. What's going on here?
Update
Oliv37 prompted me to do some tests, here are the findings:
call
is package
, then it only works when the Manager
is package
.call
is public
, it works regardless.call
is final
, the @PostConstruct
method is called only if Manager
is package
.Now the questions become: why does the method need to be public for CDI detection to work and why making it final causes the post construct method to not be called if the class is public?
Update2
Full stack trace:
org.jboss.resteasy.spi.UnhandledException: org.jboss.weld.exceptions.WeldException: Class org.jboss.weld.util.reflection.Reflections can not access a member of class com.a.b.Manager with modifiers ""
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:77)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:220)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:175)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:418)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.jboss.weld.exceptions.WeldException: Class org.jboss.weld.util.reflection.Reflections can not access a member of class com.a.b.Manager with modifiers ""
at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:437)
at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:128)
at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
at org.jboss.weld.bean.proxy.InjectionPointPropagatingEnterpriseTargetBeanInstance.invoke(InjectionPointPropagatingEnterpriseTargetBeanInstance.java:67)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100)
at com.a.b.Manager$Proxy$_$$_Weld$EnterpriseProxy$.call(Unknown Source)
at com.airhacks.boundary.Resource.go(Resource.java:16)
at com.airhacks.boundary.Resource$Proxy$_$$_WeldClientProxy.go(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:498)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402)
... 42 more
Caused by: java.lang.IllegalAccessException: Class org.jboss.weld.util.reflection.Reflections can not access a member of class com.a.b.Manager with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:491)
at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:433)
... 58 more
The short answer is - make your call
method public
The longer one goes like this - problem here is that your call
method is package protected. Accordingly to EJB spec, chapter Session Bean’s No-Interface View (quoting from 3.1 EJB spec):
Only public methods of the bean class (and any super-classes) may be invoked through the no-interface view. Attempted invocations of methods with any other access modifiers via the no-interface view reference must result in a
javax.ejb.EJBException
.
By using non-public modifier you are violating spec and the fact that in does not throw EJBException
can be either overlook in EJB impl in WFLY or a feature. One way or the other, you are in grey unspecified area.
Now as for Weld - it is trying to use reflections to access that method and invoke it, deliberately not making it accessible prior to invocation. That's where it obviously blows as you do not have access to that other method without bypassing it (with Method.setAccessible()
).
As for your side-question about final
method and @PostConstruct
not being invoked - you are breaking yet another EJB rule. This one is in 4.9.8 Session Bean’s No-Interface View
and one of the dashes there says:
Only private methods of the bean class and any superclasses except
java.lang.Object
may be declaredfinal
.
I cannot speak for why there is no exception, but this is the cause of your headaches. As for why this rule exists - well as I stated in comments Weld needs to create proxy and if the method cannot be overriden, it's impossible to weave in @PostConstruct
calls and intercept it.
Hope this answers your queries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With