Search code examples
javaweldjava-9java-modulemodule-info

Can automatic module read classes of named module in exported package in Java 9?


I am trying to see how Weld CDI container can work with JPMS. So I have the following configuration.

I have my named module and weld-se-shaded as automatic module. In my module I have

module my.module {
    requires weld.se.shaded;
    exports com.foo;
}

NewClass

package com.foo;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class NewClass {

    @Inject
    private NewBean bean;

    public void doIt() {
        bean.doIt();
    }

}

NewBean class

package com.foo;

import javax.enterprise.context.Dependent;

@Dependent
public class NewBean {

    public void doIt() {
        System.out.println("I am doing it");
    }
}

And this is the result

Sep 18, 2017 2:33:12 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 3.0.2 (2017-09-18 08:49)
Sep 18, 2017 2:33:12 PM org.jboss.weld.environment.deployment.discovery.ReflectionDiscoveryStrategy processAnnotatedDiscovery
INFO: WELD-ENV-000014: Falling back to Java Reflection for bean-discovery-mode="annotated" discovery. Add org.jboss:jandex to the classpath to speed-up startup.
Sep 18, 2017 2:33:12 PM org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Exception in thread "main" java.lang.reflect.InaccessibleObjectException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
    at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:590)
    at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:996)
    at [email protected]/org.jboss.weld.executor.AbstractExecutorServices.checkForExceptions(AbstractExecutorServices.java:72)
    at [email protected]/org.jboss.weld.executor.AbstractExecutorServices.invokeAllAndCheckForExceptions(AbstractExecutorServices.java:58)
    at [email protected]/org.jboss.weld.executor.AbstractExecutorServices.invokeAllAndCheckForExceptions(AbstractExecutorServices.java:66)
    at [email protected]/org.jboss.weld.bootstrap.ConcurrentBeanDeployer.createClassBeans(ConcurrentBeanDeployer.java:65)
    at [email protected]/org.jboss.weld.bootstrap.BeanDeployment.createBeans(BeanDeployment.java:256)
    at [email protected]/org.jboss.weld.bootstrap.WeldStartup.deployBeans(WeldStartup.java:422)
    at [email protected]/org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:83)
    at [email protected]/org.jboss.weld.environment.se.Weld.initialize(Weld.java:789)
    at my.module/com.foo.NewMain.main(NewMain.java:47)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private com.foo.NewBean com.foo.NewClass.bean accessible: module my.module does not "opens com.foo" to module weld.se.shaded
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)
    at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:176)
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:170)
    at [email protected]/org.jboss.weld.security.GetAccessibleCopyOfMember.of(GetAccessibleCopyOfMember.java:38)
    at [email protected]/org.jboss.weld.security.GetAccessibleCopyOfMember.run(GetAccessibleCopyOfMember.java:44)
    at [email protected]/org.jboss.weld.security.GetAccessibleCopyOfMember.run(GetAccessibleCopyOfMember.java:26)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at [email protected]/org.jboss.weld.injection.FieldInjectionPoint.<init>(FieldInjectionPoint.java:65)

How to explain this exception

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private com.foo.NewBean com.foo.NewClass.bean accessible: module my.module does not "opens com.foo" to module weld.se.shaded

There is a table here enter image description here from which I can understand that automatic module can read named (application) module. Then why it doesn't?


Solution

  • You should probably try replacing

    exports com.foo
    

    in your module-info.java with

    opens com.foo 
    

    The opens directive in a module declaration declares a package to be open to allow all types in the package, and all their members, not just public types and their public members to be reflected on by APIs that support private access or a way to bypass or suppress default Java language access control checks.