Jakarta EE Logo

Jakarta EE verständlich erklärt – mit diesen APIs baust du moderne Enterprise-Anwendungen: Teil 1

In diesem Beitrag geben wir einen Überblick über die wichtigsten Jakarta EE Standards und APIs, die für die Entwicklung moderner Java-Enterprise-Anwendungen unverzichtbar sind. Erfahre, wie diese Technologien helfen, skalierbare und wartbare Lösungen zu erstellen.

Enterprise-Anwendungen in Java – leistungsstark, modular und besser denn je: Mit Jakarta EE steht dir ein Standard-Set an Werkzeugen zur Verfügung, mit denen du von Messaging bis Security alles abdeckst. In dieser Beitragsreihe lernst du die wichtigsten kennen – praxisnah und auf einen Blick.

MIME-Typen clever verarbeiten – mit Jakarta Activation

Jakarta Activation hilft dir dabei, Inhalte anhand ihres MIME-Typs dynamisch zu verarbeiten – typischerweise bei E-Mails oder Webservices. Du registrierst passende Verarbeitungskomponenten, z. B. für Text oder Bilder.

<dependency>
  <groupId>jakarta.activation</groupId>
  <artifactId>jakarta.activation-api</artifactId>
</dependency>
import jakarta.activation.*;
import java.io.*;

public class MimeProcessor {

    public static void main(String[] args) {
        MailcapCommandMap commandMap = new MailcapCommandMap();
        commandMap.addMailcap("text/plain;; x-java-content-handler=com.example.TextHandler");
        commandMap.addMailcap("image/jpeg;; x-java-content-handler=com.example.ImageHandler");
        CommandMap.setDefaultCommandMap(commandMap);

        DataSource source = new FileDataSource("beispiel.txt");
        DataHandler handler = new DataHandler(source);

        try (InputStream is = handler.getInputStream()) {
            System.out.println("Typ: " + handler.getContentType());
            System.out.println("Inhalt: " + new String(is.readAllBytes()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Weniger Boilerplate dank Jakarta Annotations

Mit Jakarta Annotations stattest du Klassen mit Metadaten aus – etwa für Ressourcen-Injektion, Lebenszyklussteuerung oder Konfiguration. So reduziert sich dein Code enorm.

<dependency>
  <groupId>jakarta.annotation</groupId>
  <artifactId>jakarta.annotation-api</artifactId>
</dependency>
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import javax.sql.DataSource;

public class ResourceBean {

    @Resource(name = "jdbc/MyDataSource")
    private DataSource dataSource;

    @PostConstruct
    public void init() {
        System.out.println("Datenquelle fertig: " + dataSource);
    }
}

Sicherheit ab Werk – mit Jakarta Authentication

Mit Jakarta Authentication kannst du eigene Login-Mechanismen erstellen. Der Container übernimmt die Integration – du kümmerst dich nur um die Regeln.

<dependency>
  <groupId>jakarta.authentication</groupId>
  <artifactId>jakarta.authentication-api</artifactId>
</dependency>
import jakarta.security.enterprise.*;
import jakarta.security.enterprise.authentication.mechanism.http.*;
import jakarta.security.enterprise.identitystore.*;
import jakarta.security.enterprise.credential.*;
import jakarta.inject.Inject;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;

@BasicAuthenticationMechanismDefinition(realmName = "example")
@EmbeddedIdentityStoreDefinition({
    @EmbeddedIdentityStoreDefinition.User(name = "user", password = "password", roles = "user"),
    @EmbeddedIdentityStoreDefinition.User(name = "admin", password = "admin", roles = "admin")
})
public class SimpleAuthenticationMechanism implements AuthenticationMechanism {

    @Inject
    private IdentityStoreHandler identityStoreHandler;

    @Override
    public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext context) throws ServletException {
        if (context.isProtected() && !context.isAuthenticationCompleted()) {
            UsernamePasswordCredential credential = new UsernamePasswordCredential(
                request.getParameter("username"),
                request.getParameter("password")
            );

            CredentialValidationResult result = identityStoreHandler.validate(credential);

            if (result.getStatus() == CredentialValidationResult.Status.VALID) {
                return context.notifyContainerAboutLogin(result.getCallerPrincipal(), result.getCallerGroups());
            } else {
                return context.responseUnauthorized();
            }
        }
        return context.doNothing();
    }
}

Rollenbasiert zugreifen – mit Jakarta Authorization

Mit der Authorization-API vergibst du klar definierte Rollen und schützt Methoden direkt im Code – einfach und sicher.

<dependency>
  <groupId>jakarta.authorization</groupId>
  <artifactId>jakarta.authorization-api</artifactId>
</dependency>
import jakarta.annotation.security.*;

@DeclareRoles({"user", "admin"})
public class SecureResource {

    @RolesAllowed("admin")
    public void adminOnly() {
        System.out.println("Admin-Zugriff erlaubt.");
    }

    @RolesAllowed({"user", "admin"})
    public void forUsers() {
        System.out.println("Zugriff für Benutzer oder Admin.");
    }
}

Große Datenmengen effizient verarbeiten – mit Jakarta Batch

Perfekt für wiederkehrende Jobs wie Rechnungsversand, Datenimporte oder regelmäßige Prozesse: Jakarta Batch bietet dir eine XML-gesteuerte Verarbeitung mit voller Kontrolle.

<dependency>
  <groupId>jakarta.batch</groupId>
  <artifactId>jakarta.batch-api</artifactId>
</dependency>
import jakarta.batch.api.AbstractBatchlet;
import jakarta.batch.api.listener.JobListener;
import jakarta.batch.runtime.context.JobContext;
import jakarta.inject.*;

@Named
public class SimpleBatchlet extends AbstractBatchlet {

    @Inject
    private JobContext jobContext;

    @Override
    public String process() {
        String propValue = jobContext.getProperties().getProperty("batchProp");
        System.out.println("Batchlauf mit Property: " + propValue);
        return "COMPLETED";
    }
}

@Named
public class CustomJobListener implements JobListener {

    @Override
    public void beforeJob() {
        System.out.println("Job startet gleich.");
    }

    @Override
    public void afterJob() {
        System.out.println("Job abgeschlossen.");
    }
}
<job id="simpleBatchJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
    <step id="step1">
        <batchlet ref="SimpleBatchlet">
            <properties>
                <property name="batchProp" value="value1"/>
            </properties>
        </batchlet>
        <listeners>
            <listener ref="CustomJobListener"/>
        </listeners>
    </step>
</job>

CDI: Saubere Abhängigkeiten und Lebenszyklussteuerung

Mit Jakarta CDI steuerst du den Lebenszyklus und die Injektion von Beans – ideal für modulare, testbare Architekturen.

<dependency>
  <groupId>jakarta.enterprise</groupId>
  <artifactId>jakarta.enterprise.cdi-api</artifactId>
</dependency>
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

@RequestScoped
public class MessagePrinter {

    @Inject
    private MessageService messageService;

    public void printMessage() {
        System.out.println(messageService.getMessage());
    }
}

@ApplicationScoped
public class MessageService {
    public String getMessage() {
        return "Hello, CDI!";
    }
}

Nebenläufigkeit kontrolliert umgesetzt – mit Jakarta Concurrency

Du möchtest Tasks asynchron ausführen – aber containerfreundlich und verwaltet? Jakarta Concurrency macht’s möglich.

<dependency>
  <groupId>jakarta.enterprise.concurrent</groupId>
  <artifactId>jakarta.enterprise.concurrent-api</artifactId>
</dependency>
import jakarta.annotation.Resource;
import jakarta.enterprise.concurrent.ManagedExecutorService;
import java.util.concurrent.*;

public class ConcurrencyExample {

    @Resource
    private ManagedExecutorService managedExecutorService;

    public void executeTask() throws Exception {
        Future<String> result = managedExecutorService.submit(() -> "Task abgeschlossen!");
        System.out.println(result.get());
    }
}

Konfiguration zentral verwalten – mit Jakarta Config

Ob Umgebungsvariablen, Properties-Dateien oder Cloud – Konfigurationen kannst du mit Jakarta Config typisiert und zentral einlesen.

<dependency>
  <groupId>jakarta.config</groupId>
  <artifactId>jakarta.config-api</artifactId>
</dependency>
app.name=JakartaApp
max.users=100
import jakarta.config.Config;
import jakarta.config.ConfigProvider;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class AppConfig {

    private final String appName;
    private final int maxUsers;

    public AppConfig() {
        Config config = ConfigProvider.getConfig();
        this.appName = config.getValue("app.name", String.class);
        this.maxUsers = config.getValue("max.users", Integer.class);
    }

    public void printConfig() {
        System.out.println("App: " + appName);
        System.out.println("Maximale Nutzer: " + maxUsers);
    }
}

Externe Systeme anbinden – mit Jakarta Connectors

Wenn du mit einem ERP, CRM oder anderen Enterprise-System kommunizieren musst, helfen dir Jakarta Connectors über standardisierte Ressourcen-Adapter.

<dependency>
  <groupId>jakarta.resource</groupId>
  <artifactId>jakarta.resource-api</artifactId>
</dependency>
import jakarta.annotation.Resource;
import jakarta.resource.cci.*;

public class SimpleJcaExample {

    @Resource(name = "eis/SimpleConnectionFactory")
    private ConnectionFactory connectionFactory;

    public void executeSimpleInteraction() {
        try (Connection connection = connectionFactory.getConnection()) {
            System.out.println("EIS-Verbindung erfolgreich.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Datenzugriff leicht gemacht – mit Jakarta Data

Jakarta Data bietet dir ein Repository-Vorgehen wie in Spring: Methoden wie findByName generieren automatisch deine Queries.

<dependency>
  <groupId>jakarta.data</groupId>
  <artifactId>jakarta.data-api</artifactId>
</dependency>
import jakarta.data.repository.CrudRepository;

public interface ProductRepository extends CrudRepository<Product, Long> {
    List<Product> findByName(String name);
}

Deployment-Daten per API – mit Jakarta Deployment

Diese API wird häufig von Containern genutzt, um Informationen über Deployments zu erhalten – für dich als Entwicklerin meist im Hintergrund relevant.

<dependency>
  <groupId>jakarta.deployment</groupId>
  <artifactId>jakarta.deployment-api</artifactId>
</dependency>

Simple Injektion ohne Lifecycle – mit Jakarta Inject

Für einfache Dependency Injection ohne Kontextverwaltung kommt Jakarta Inject zum Einsatz – geradlinig und effizient.

<dependency>
  <groupId>jakarta.inject</groupId>
  <artifactId>jakarta.inject-api</artifactId>
</dependency>
import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named
public class SimpleService {
    public String getInfo() {
        return "Hello from SimpleService!";
    }
}

public class Consumer {

    @Inject
    private SimpleService simpleService;

    public void displayServiceInfo() {
        System.out.println(simpleService.getInfo());
    }
}

Fazit: Der Werkzeugkasten für moderne Java-Anwendungen

Ob Datei-Handling, Datenmanagement oder Sicherheit: Jakarta EE liefert dir robuste Bausteine, um skalierbare, wartbare und standardisierte Enterprise-Anwendungen zu entwickeln. Schritt für Schritt kombinierst du genau die Komponenten, die du brauchst.1

Fortsetzung folgt …
Im zweiten Teil zeigen wir dir APIs für JSON, Messaging, Webservices u. v. m.

Weiterführende Links

Jakarta EE ist ein Projekt der Eclipse Foundation. Das Logo ist ein eingetragenes Markenzeichen.

Marius Dienel

Über MICH

Marius Dienel ist Fachinformatiker im Bereich Anwendungsentwicklung und arbeitet seit 2019 bei doubleSlash. Als Softwareentwickler hat er unter anderem Fachwissen in den Bereichen Java EE, Spring und OSGi. Zudem beschäftigt er sich für das Produkt Business Filemanager mit Themen rund um den Bereich DevOps.

Alle Beiträge von Marius Dienel

Mehr erfahren

Weitere Infos auf unserer Website und in unserem Newsletter

Pfeil hoch