dante33
dante33

Reputation: 41

Exception: java.lang.NoClassDefFoundError: javax/activation/DataHandler

I am creating a chat application in javafx and I am trying to use the javamail api to verify the user's email. The problem is that when I run the application it shows me the following message: java.lang.NoClassDefFoundError: javax/activation/DataHandler I am using java 17, javafx 17, netbeans ide 12.0.

This is the code I have written:

package chat;

import java.util.Properties;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class Chat extends Application{
   private Parent raiz;
   private Scene scene;
   private Stage stg1;
   private Image imagenx;

   @Override
   public void start(Stage stage) throws Exception {
      raiz = FXMLLoader.load(getClass().getResource("Chat.fxml"));
      scene = new Scene(raiz);
      scene.setUserAgentStylesheet(getClass().getResource("chat.css").toExternalForm());
      stg1 = stage;
      stg1.setScene(scene);
      imagenx = new Image(getClass().getResource("icono.jpg").toString());
      stg1.getIcons().add(imagenx);
      stg1.setTitle("Video chat");
      stg1.setWidth(800);
      stg1.setHeight(600);
      stg1.show();
   }

   private void enviarMail(String destinatario){
      String remitente = "mi remitente";
      String asunto = "enviar correo de confirmacion";
      String cuerpo = "mensaje a enviar";
      String clv = "1234";
    
      Properties props = System.getProperties();
      props.put("mail.smtp.host", "smtp.gmail.com");
      props.put("mail.smtp.user", remitente);
      props.put("mail.smtp.clave", clv);
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.port", "587");
    
      Autenticador aut = new Autenticador(remitente,clv);
      sesion = Session.getInstance(props,aut);
      mm = new MimeMessage(sesion);

      try{
        mm.setFrom(new InternetAddress(remitente));
        mm.addRecipients(Message.RecipientType.TO, destinatario);
        mm.setSubject(asunto);
        mm.setText(cuerpo);
        try(Transport transport = sesion.getTransport("smtp")) {
            transport.connect("smtp.gmail.com", remitente, clv);
            try{
                transport.sendMessage(mm, mm.getAllRecipients());
            }
            catch(MessagingException ex){
                System.out.println(ex);
            }
        }
        catch(Exception ex){
            System.out.println(ex);
        }
      }
      catch(MessagingException ex){
        System.out.println(ex);
      }
   }

   public static void main(String[] args) {
      launch(args);
      enviarMail("[email protected]");
   }
}

class Autenticador extends Authenticator{
   private String smtp_usuario = "";
   private String smtp_pass = "";

   Autenticador() {}

   Autenticador(String user , String pass) {
     this.smtp_usuario = user;
     this.smtp_pass = pass;
   }

   @Override
   public PasswordAuthentication getPasswordAuthentication() {
     return new PasswordAuthentication(this.smtp_usuario, 
     this.smtp_pass);
   }
}

The error is generated in this line of code: mm = new MimeMessage(sesion);

change the library from javax.mail to jakarta.mail, update netbeans to version 12.6, I have version java 17 installed, add the jar jakarta.activation, but when I run the project in netbeans this error is generated: java.lang.NoClassDefFoundError: jakarta/activation/DataHandler. Googling I found that I should add the following dependency:

<dependency>
  <groupId>jakarta.activation</groupId>
  <artifactId>jakarta.activation-api</artifactId>
  <version>2.0.1</version>
</dependency>

query, where should I add the pom.xml file with the dependency and how to use the jakarta.activation jar? I'm self-taught so maybe the question is very obvious.Apart from JavaMail is there any other library that I could use to send email?

Upvotes: 2

Views: 9134

Answers (1)

jewelsea
jewelsea

Reputation: 159281

Update 2025

According to the jakarta mail updates page.

August 18, 2021 - Jakarta Mail implementation moves to Eclipse Angus To break tight integration between Jakarta Mail Specification API and the implementation, sources of the implementation were moved to the new project - Eclipse Angus - and further development continues there. Eclipse Angus is the direct successor of JavaMail/JakartaMail.

Therefore, you may consider using Angus Mail rather than Jakarta Mail as an implementation (as far as I know it is largely compatible, just different maven coordinates.

<dependency>
    <groupId>org.eclipse.angus</groupId>
    <artifactId>angus-mail</artifactId>
    <version>2.0.3</version>
</dependency>

That dependency should transitively bring in angus activation, which implements the jakarta.activation:jakarta.activation-api.

<dependency>
    <groupId>org.eclipse.angus</groupId>
    <artifactId>angus-activation</artifactId>
    <version>2.0.2</version>
    <scope>runtime</scope>
</dependency>

Original answer

Include the Jakarta Activation library

Jakarta Mail is the modern packaging for Java mail.

See the Jakarta Mail readme:

Jakarta Mail requires Jakarta Activation 2.0.0 or newer.

Jakarta Activation website and download.

If you use a build tool (highly recommended), such as Maven or Gradle, it will likely already add a transitive dependency on Jakarta activation to your build when you add the Jakarta mail dependency. If it doesn’t, then add the dependency yourself.

If you have additional issues

Use recent versions of all software, JDK/JavaFX 17.0.2+, JakartaMail 2.0.1+. See:

Also, see jakarta mail compatability notes

In this release the name of that module is changed to "jakarta.mail".

So use jakarta.mail in your module-info.Java when requiring the module

OR

Place jakarta.mail in your --add-module switch, if adding modules via command line switches instead of module-info.java.

Example App

The following app compiles and runs but will fail when trying to send mail due to incorrect authentication, however, I think it demonstrates how to fix the issues with class resolution asked in the question.

Things it does:

  1. requires jakarta.mail in the module-info.

  2. Adds a dependency on jakarta mail in the pom.xml.

    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>jakarta.mail</artifactId>
        <version>2.0.1</version>
    </dependency>
    
  3. An explicit dependency on the jakarta activation framework library is not needed as it brought it via a transitive dependency on jakarta.mail.

  4. Changes the imports to use the jakarta.mail package instead of the java.mail package.

  5. Makes minor changes to the example from the question to allow it to compile and run.

module-info.java

module com.example.maildemo {
    requires javafx.controls;
    requires jakarta.mail;

    exports com.example.maildemo;
}

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>mail-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>mail-demo</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>5.7.1</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>jakarta.mail</artifactId>
            <version>2.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

MailDemoApp.java

package com.example.maildemo;

import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

import java.util.Properties;

public class MailDemoApp extends Application {

    @Override
    public void start(Stage stage) {
        Button sendMailButton = new Button("Send mail");
        sendMailButton.setOnAction(e -> enviarMail("[email protected]"));
        stage.setScene(new Scene(sendMailButton));
        stage.show();
    }

    private void enviarMail(String destinatario) {
        String remitente = "127.0.0.1";
        String asunto = "enviar correo de confirmacion";
        String cuerpo = "mensaje a enviar";
        String clv = "1234";

        Properties props = System.getProperties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.user", remitente);
        props.put("mail.smtp.clave", clv);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.port", "587");

        MyAuthenticator aut = new MyAuthenticator(remitente, clv);
        Session session = Session.getInstance(props, aut);
        MimeMessage mm = new MimeMessage(session);

        try {
            mm.setFrom(new InternetAddress(remitente));
            mm.addRecipients(Message.RecipientType.TO, destinatario);
            mm.setSubject(asunto);
            mm.setText(cuerpo);

            try (Transport transport = session.getTransport("smtp")) {
                transport.connect("smtp.gmail.com", remitente, clv);
                transport.sendMessage(mm, mm.getAllRecipients());
            }
        } catch (MessagingException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class MyAuthenticator extends Authenticator {
    private String smtp_usuario = "";
    private String smtp_pass = "";

    MyAuthenticator(String user, String pass) {
        this.smtp_usuario = user;
        this.smtp_pass = pass;
    }

    @Override
    public PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(this.smtp_usuario,
                this.smtp_pass);
    }
}

Maven dependency tree

[INFO] --- maven-dependency-plugin:3.2.0:tree (default-cli) @ mail-demo ---
[INFO] com.example:mail-demo:jar:1.0-SNAPSHOT
[INFO] +- org.openjfx:javafx-controls:jar:17.0.2:compile
[INFO] |  +- org.openjfx:javafx-controls:jar:win:17.0.2:compile
[INFO] |  \- org.openjfx:javafx-graphics:jar:17.0.2:compile
[INFO] |     +- org.openjfx:javafx-graphics:jar:win:17.0.2:compile
[INFO] |     \- org.openjfx:javafx-base:jar:17.0.2:compile
[INFO] |        \- org.openjfx:javafx-base:jar:win:17.0.2:compile
[INFO] \- com.sun.mail:jakarta.mail:jar:2.0.1:compile
[INFO]    \- com.sun.activation:jakarta.activation:jar:2.0.1:compile

Upvotes: 2

Related Questions