Hot questions for Using Joda-Time in maven

Question:

I'm using this Github project to get exposed to the new modular features in Java 9. I would like to add dependencies to the project and be able to build a native image. However, when I try to add a new dependency to the pom.xml, and add the requires statement to the module-info.java, I get a the following error from the maven-jlink-plugin:

Error: module-info.class not found for joda.time module

I'm trying to use this as a proof of concept that I can deploy images using the new linking phase, but naturally I need to be able to have external dependencies and I need to use maven (work constraint).

Changes to mod-jar/pom.xml

...
 <dependencies>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.9.9</version>
    </dependency>
  </dependencies>
...

mod-jar/module-info.java

module com.soebes.nine.jar {
  requires java.base;
  requires joda.time;
  exports com.soebes.example.nine.jar;
}

Logs:

[INFO] --- maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) @ mod-jlink ---
[INFO] Toolchain in maven-jlink-plugin: jlink [ /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/jlink ]
[INFO] The following dependencies will be linked into the runtime image:
[INFO]  -> module: com.soebes.nine.one ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-1/target/jmods/com.soebes.nine.one.jmod )
[INFO]  -> module: com.soebes.nine.two ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-2/target/jmods/com.soebes.nine.two.jmod )
[INFO]  -> module: com.soebes.nine.jar ( /Users/sebastianrestrepo/Projects/jdk9-jlink-jmod-example/maven-example/mod-jar/target/com.soebes.nine.jar-1.0-SNAPSHOT.jar )
[INFO]  -> module: joda.time ( /Users/sebastianrestrepo/.m2/repository/joda-time/joda-time/2.9.9/joda-time-2.9.9.jar )
[ERROR] 
Error: module-info.class not found for joda.time module
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] parent ............................................. SUCCESS [  1.460 s]
[INFO] com.soebes.nine.one ................................ SUCCESS [  2.022 s]
[INFO] com.soebes.nine.two ................................ SUCCESS [  1.392 s]
[INFO] com.soebes.nine.jar ................................ SUCCESS [  1.388 s]
[INFO] mod-jlink .......................................... FAILURE [  1.061 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.911 s
[INFO] Finished at: 2017-11-03T15:27:35-04:00
[INFO] Final Memory: 26M/981M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jlink-plugin:3.0.0-alpha-1:jlink (default-jlink) on project mod-jlink: 

I would really appreciate any help. Thanks.


Answer:

This has not much to do with the plugin I believe. Module joda.time in your case seems to be an automatic module.

The jlink tool does not support linking of automatic modules because they can rely on the arbitrary content of the classpath, which goes against the idea of a self-contained Java runtime.

So there are two ways to fix this probably :-

  • (you don't own the jar) Temporarily go ahead create a module-info.java[you could use jdeps tool for it] and update the jar[using jar tool] with the corresponding compiled class as in projects under Java 9.

  • (you own the dependency) Permanently migrate the jar to Java 9 itself, where it would consist of the module-info.class by itself after being compiled and packaged.

Question:

I am trying build a java project with maven. I check maven command through mvn -v and it gives following output

Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T18:41:47+02:00)
Maven home: C:\Program Files\Apache\Maven\apache-maven-3.3.9\bin\..
Java version: 1.8.0_101, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk1.8.0_101\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"

I add org.joda.time.LocalTime to HelloWorld.java as follows

package hello;

import org.joda.time.LocalTime;

public class HelloWorld {
    public static void main(String[] args) {
        LocalTime currentTime = new LocalTime();
        System.out.println("The current local time is: " + currentTime);
        Greeter greeter = new Greeter();
        System.out.println(greeter.sayHello());
    }
}

Therefore I add joda-time dependency to my pom.xml. Here is my pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework</groupId>
    <artifactId>gs-maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

    <dependencies>
        <!-- tag::joda[] -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.2</version>
        </dependency>
        <!-- end::joda[] -->
        <!-- tag::junit[] -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- end::junit[] -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>hello.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Whenever I am going to run the mvn compile it gives the output as

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building gs-maven 0.1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ gs-maven ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory H:\Projects\JAVA\web\unzipped\gs-maven\initial\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ gs-maven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 2 source files to H:\Projects\JAVA\web\unzipped\gs-maven\initial\target\classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[3,21] package org.joda.time does not exist
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[7,9] cannot find symbol
  symbol:   class LocalTime
  location: class hello.HelloWorld
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[7,37] cannot find symbol
  symbol:   class LocalTime
  location: class hello.HelloWorld
[INFO] 3 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.647 s
[INFO] Finished at: 2016-10-03T09:11:07+03:00
[INFO] Final Memory: 14M/114M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project gs-maven: Compilation failure: Compilation failure:
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[3,21] package org.joda.time does not exist
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[7,9] cannot find symbol
[ERROR] symbol:   class LocalTime
[ERROR] location: class hello.HelloWorld
[ERROR] /H:/Projects/JAVA/web/unzipped/gs-maven/initial/src/main/java/hello/HelloWorld.java:[7,37] cannot find symbol
[ERROR] symbol:   class LocalTime
[ERROR] location: class hello.HelloWorld
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Please let me inform what I am doing wrong.

N.B: I am just following Building Java Projects with Maven tutorial as a beginner.


Answer:

Your Maven is reading Java version as 1.8.0_101, Where as the pom.xml is not updated

1) Try installing the required verison. Have the JAVA_HOME and pom.xml updated to the same jdk installation path

2) mvn clean install - What this does is clear any compiled files you have, making sure that you're really compiling each module from scratch.

Question:

I it seems to be a very stupid question, because Joda-Time is easy to use that there is no explanation about how to use it in its user guide (and I don’t find useful answers on the web).

I try to use the method of Joda-Time which can calculate the duration between two dates. I have to compare the current date with an other date.

I cannot use LocalDateTime because the class does not exist (so I created it), but I saw that "duration" need to implement ReadableDuration in the class but this interface does not exist too...

I tried to write :

DateTime dt = new DateTime(juDate);

and

public class LocalDateTime implements ReadableDuration{

    public LocalDateTime() {
    }
}

I have install Joda-Time by dependency on Maven, I have the 2.9.1 version.

<dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.9.1</version>
</dependency>

Can you explain to a newbie how to do, please ?


Answer:

java.time

The time api has been reworked in JDK 8 and resembles a lot Joda-Time (I think Joda-Time is implementation of some JSR).

Citation http://www.joda.org/joda-time/

Joda-Time is the de facto standard date and time library for Java. From Java SE 8 onwards, users are asked to migrate to java.time (JSR-310).

So just create a JDK 8 project and your LocalDate and LocalTime classes should be available in package java.time

After that just follow official oracle tutorial:

http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html

GLHF

Question:

I am using IntelliJ 14

I want to add joda.time lib in my project. When I add this lib manually (copy the jar file into lib repository, and add reference in Project Structure) everything work good, I can use the library in a servlet and show the result in a jsp.

But in second step I create the same project but I am using maven with a pom.xml file. I add this dependency :

<dependencies>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.1</version>
    </dependency>
</dependencies>

Maven download automatically the lib, in my Project Structure every thing looks like it's good, I run the project ... no error, but when I go to my webpage I have an error in my navigator :

java.lang.NoClassDefFoundError: org/joda/time/DateTime
com.sdzee.servlets.ServletTest.doGet(ServletTest.java:47)
javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

The project is exactly the same, I just use Maven for use the lib.

Do you have ideas?

My Servlet line 47 for example :

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    DateTime dt = new DateTime();
    Integer jourDuMois = dt.getDayOfMonth();
}

Answer:

You should check in your pom.xml if the packaging type is explicitly set to war. If not, maven won't use the maven-war-plugin to bundle your application correctly with all your referenced libraries, e.g. joda-time.

so You should have:

<packaging>war</packaging>

See also for reference: Maven Reference Book

Question:

I'm trying to shade Joda time 2.9.2 into my final jar file, using the maven shade plugin. But Joda time's classes are not getting added to the final jar, some packages and other files are getting added, but not the .class files.

Here's my pom.xml;

<?xml version="1.0" encoding="UTF-8"?>
<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>me.ninjoh</groupId>
<artifactId>nincore</artifactId>
<version>2.0.0</version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <local.maven.repository>file:///Users/LegitAdmin/.m2/repository</local.maven.repository>
</properties>

<repositories>
    <repository>
        <id>mcapi</id>
        <url>http://build.mc-api.net/plugin/repository/everything/</url>
    </repository>

    <repository>
        <id>spigot-repo</id>
        <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
    </repository>

</repositories>

<dependencies>
    <dependency>
        <groupId>net.mcapi.uuid</groupId>
        <artifactId>uuid-java</artifactId>
        <version>1.1.2</version>
    </dependency>

    <!--Spigot API-->
    <dependency>
        <groupId>org.spigotmc</groupId>
        <artifactId>spigot-api</artifactId>
        <version>1.8.8-R0.1-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>

    <!--Bukkit API-->
    <dependency>
        <groupId>org.bukkit</groupId>
        <artifactId>bukkit</artifactId>
        <version>1.8.8-R0.1-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>

    <!-- Joda Time-->
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.9.2</version>
    </dependency>

    <!-- Jbcrypt -->
    <dependency>
        <groupId>org.mindrot</groupId>
        <artifactId>jbcrypt</artifactId>
        <version>0.3m</version>
    </dependency>

    <!-- Jansi (for color in console) -->
    <dependency>
        <groupId>org.fusesource.jansi</groupId>
        <artifactId>jansi</artifactId>
        <version>1.11</version>
    </dependency>

    <!-- Jetbrains annotations -->
    <dependency>
        <groupId>org.jetbrains</groupId>
        <artifactId>annotations-java5</artifactId>
        <version>15.0</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <minimizeJar>true</minimizeJar>
                <artifactSet>
                    <includes>
                        <include>org.jetbrains:annotations-java5</include>
                        <include>org.fusesource.jansi:jansi</include>
                        <include>org.mindrot:jbcrypt</include>
                        <include>net.mcapi.uuid:uuid-java</include>
                        <include>joda-time:joda-time</include>
                    </includes>
                </artifactSet>
                <relocations>

                    <relocation>
                        <pattern>org.jetbrains</pattern>
                        <shadedPattern>me.ninjoh.common.org.jetbrains</shadedPattern>
                    </relocation>

                    <relocation>
                        <pattern>org.fusesource.jansi</pattern>
                        <shadedPattern>me.ninjoh.common.org.fusesource.jansi</shadedPattern>
                    </relocation>

                    <relocation>
                        <pattern>org.mindrot.jbcrypt</pattern>
                        <shadedPattern>me.ninjoh.common.org.mindrot.jbcrypt</shadedPattern>
                    </relocation>

                    <relocation>
                        <pattern>net.mcapi.uuid</pattern>
                        <shadedPattern>me.ninjoh.common.net.mcapi.uuid</shadedPattern>
                    </relocation>

                </relocations>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/license/**</exclude>
                            <exclude>META-INF/*</exclude>
                            <exclude>META-INF/maven/**</exclude>
                            <exclude>LICENSE</exclude>
                            <exclude>NOTICE</exclude>
                            <exclude>/*.md</exclude>
                            <exclude>/.gitignore</exclude>
                            <exclude>/*.txt</exclude>
                            <exclude>build.properties</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
        </plugin>
    </plugins>
</build>

<distributionManagement>
    <repository>
        <id>local-repository</id>
        <url>${local.maven.repository}</url>
    </repository>
</distributionManagement>

And here are the contents of the final jar file; http://pastebin.com/TXzB9vTv

Why aren't Joda time's classes being included in the final jar? How would I fix this?

For future readers: When using <minimizeJar>true</minimizeJar> you should explicitly include the dependency (in this case, joda time) in the filters section. Otherwise it can be 'optimized' away.


Answer:

The release v2.9.3 is not yet out. The latest one is v2.9.2.

Update:

After clarification of version problem, following description of maven-shade-plugin is important.

Besides user-specified filters, the plugin can also be configured to automatically remove all classes of dependencies that are not used by the project, thereby minimizing the resulting uber JAR

So either make sure that your project really uses Joda-Time, or remove the tag entry

<minimizeJar>true</minimizeJar>

Question:

I have identified that I need to use

<mapping class="org.jadira.usertype.dateandtime.joda.PersistentLocalDate" />
<mapping class="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime" />

classes for persisting in the database. I am really confused regarding which jars to download for these two classes I want to persist.

Should I use joda time classes and usertype classes to persist, what is the relation between them. I am using hibernate 4.

I also see that there is 3.2.0GA and 3.2.0CR11 what does this mean. In the maven repository for many of the packages it is written adds hibernate support! but which version? I am trying to solve this from 3 days now...


Answer:

The Joda time User Type classes are not meant for mappings. You map Entities, not UserTypes.

For start, please check this introductory article on Hibernate Types.

Hibernate defines the following data structures:

  1. An Entity is the Object equivalent of a database row. It has an @Id that maps to the associated row's primary key.

  2. An Embeddable is an Object that maps to one or more columns except the primary key. It's always depended on the parent Entity.

  3. Both Entity and Embeddable may contain non-primary key column mappings, and the Java-to-SQL type bridge is being handled by Hibernate Types.

  4. You can define your own User Types to represent other structures such as Money or Currency.

So, the Jadira types are bridging the Joda DateTime Object types to DATE, TIME and TIMESTAMP SQL types. If you don't need to use Joda, you'd have to rely on java.util.date, java.util.Calendar or java.sql.Date for your Entity property types.