Search code examples
javamavenjava-modulejava-platform-module-systemmodule-info

Use java automatic module cdi.api with maven and java 9+


I want to use CDI functionality in a java module. I'd like my code to remain generic and do not depend on a particular implementation.

I use Java 11 and Maven 3.6.0.

For a simplicity, my goal is reduced to importing package javax.enterprise.context in a java file. When I do so without module (without module-info.java) every thing works well.

Now when I add a module-info.java without requiring other modules, I get the following error message:
package javax.enterprise.context is not visible (package javax.enterprise.context is declared in the unnamed module, but module javax.enterprise.context does not read it)

Until now everything is OK. This message makes sens since I didn't require the CDI module.

To fix this I add requires cdi.api; to my module-info.java, only to get the following error:
module not found: cdi.api

My understanding is that the CDI library should take an automatic module name inspired by the jar file's name. When I run maven with -X directive I see cdi-api-2.0.jar in my classpath. I believe, correct if I'm wrong, this should translate to cdi.api automatic module name. But still this doesn't work.

Here is my minimal example:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.acme</groupId>
  <artifactId>test.java.cdi</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
           <groupId>javax.enterprise</groupId>
           <artifactId>cdi-api</artifactId>
           <version>2.0</version>
           <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

src/main/java/module-info.java:

module com.acme.test.cid {
    requires cdi.api;
}

src/main/java/com/acme/Main.java

package com.acme;

import javax.enterprise.context.*;

class Main {}

Any insights are highly appreciated.


Solution

  • When I run maven with -X directive I see cdi-api-2.0.jar in my classpath. I believe, correct if I'm wrong, this should translate to cdi.api automatic module name. But still this doesn't work.

    No, the modules resulting into the classpath are translated into the unnamed module.

    module not found: cdi.api

    Indicates that the cdp.api module was not found on the modulepath.


    I tried reproducing the same, yet the same reproducible code worked fine for me, but notice my logs read :

    [DEBUG] Classpath:
    [DEBUG] Modulepath:
    [DEBUG]  .../Desktop/cdipi/target/classes
    [DEBUG]  .../.m2/repository/javax/enterprise/cdi-api/2.0/cdi-api-2.0.jar
    [DEBUG]  .../.m2/repository/javax/el/javax.el-api/3.0.0/javax.el-api-3.0.0.jar
    [DEBUG]  .../.m2/repository/javax/interceptor/javax.interceptor-api/1.2/javax.interceptor-api-1.2.jar
    [DEBUG]  .../.m2/repository/javax/inject/javax.inject/1/javax.inject-1.jar
    [DEBUG] Source roots:
    [DEBUG]  .../Desktop/cdipi/src/main/java
    [DEBUG]  .../Desktop/cdipi/target/generated-sources/annotations
    

    Just make sure the maven-compiler-plugin in use if 3.6.0 or above to support the modulepath added in Java9 and above. You can do it as specified in this answer.