NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 3 - Vytvoření prvního modulu v Javě

V předchozí lekci, Classloader a první modul v Javě, jsme se dozvěděli, co je to classloader a jak funguje načítání tříd v Javě. Popsali jsme si různé typy modulů a ukázali jsme si, jak takový modul definujeme.

V dnešní lekci našeho Java tutoriálu si ukážeme, jak vytvořit moduly a jak funguje komunikace mezi nimi. Projekt bude řízen Mavenem. Cílem bude přepsat Zdraviče z OOP lekcí na zdraviče z modulů.

Struktura projektu

Budeme mít celkem tři moduly:

  • hlavní - zde bude main metoda,
  • api - zde bude jedno rozhraní definující metodu pro zdraviče,
  • impl - implementace různých zdravičů.

Základní myšlenka tohoto návrhu je oddělení specifikace od implementace. V budoucnu můžeme například napsat další modul, ve kterém budeme chtít napsat další druh zdraviče. Můžeme to brát jako rozšíření stávající implementace.

Tvorba projektu

Začneme tvorbou nového projektu. Jak už bylo řečeno, projekt bude řízen Mavenem.

Protože budeme tvořit vlastní strukturu projektu, nepoužijeme žádný archetyp, který nám Maven nabízí. Zároveň budeme složky vytvářet mimo naše vývojové prostředí.

Nejdříve si založíme novou složku s projektem. Složku nazveme cz.itnetwork.moduly. Do ní přidáme tři podsložky: cz.itnetwork.moduly.zdravic, cz.itnetwork.moduly.zdravic.api, cz.itnetwork.moduly.zdravic.impl a soubor pom.xml. V každé podsložce také vytvoříme další soubor pom.xml. Dále do každé podsložky přidáme vnořené složky: src/main/java/.

Vznikne nám následující adresářová struktura:

cz.itnetwork.moduly
|-cz.itnetwork.moduly.zdravic
| |-src
| | |-main
| | | |-java
| |-pom.xml
|-cz.itnetwork.moduly.zdravic.api
| |-src
| | |-main
| | | |-java
| |-pom.xml
|-cz.itnetwork.moduly.zdravic.impl
| |-src
| | |-main
| | | |-java
| |-pom.xml
|-pom.xml

Maven konfigurace

Teď postupně vyplníme jednotlivé pom.xml soubory. Hlavní konfigurační pom.xml soubor bude zatím obsahovat pouze základní informace o projektu. Dále bude obsahovat seznam (maven) submodulů:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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>cz.itnetwork.moduly</groupId>
  <artifactId>cz.itnetwork.moduly</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>cz.itnetwork.moduly</name>

  <properties>
    <!-- https://maven.apache.org/general.html#encoding-warning -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>18</maven.compiler.source>
    <maven.compiler.target>18</maven.compiler.target>
  </properties>

  <modules>
    <module>cz.itnetwork.moduly.zdravic</module>
    <module>cz.itnetwork.moduly.zdravic.api</module>
    <module>cz.itnetwork.moduly.zdravic.impl</module>
  </modules>

  <build>
      <pluginManagement>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <version>3.8.1</version>
                  <configuration>
                      <source>${maven.compiler.source}</source>
                      <target>${maven.compiler.target}</target>
                  </configuration>
              </plugin>
          </plugins>
      </pluginManagement>
  </build>

</project>

Je velmi důležité, aby bylo přítomno nastavení maven compiler pluginu. Zejména definice source a target. Pokud toto nastavení vynecháme, budeme se později potýkat s problémy, protože kompilátor nebude schopný najít Java modul!

Konfigurační soubory pom.xml v submodulech budou všechny zatím vypadat stejně. Lišit se budou pouze v názvu. Případné další úpravy provedeme až budou potřeba:

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

  <parent>
    <groupId>cz.itnetwork.moduly</groupId>
    <artifactId>cz.itnetwork.moduly</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <version>1.0-SNAPSHOT</version>
  <artifactId>cz.itnetwork.moduly.zdravic</artifactId> <!-- na tomto řádku upravte artifactId dle modulu zdravic/zdravic.api/zdravic.impl -->
  <name>cz.itnetwork.moduly.zdravic</name> <!-- na tomto řádku upravte name dle modulu zdravic/zdravic.api/zdravic.impl -->

</project>

Otevření projektu ve vývojovém prostředí

Když už máme založený projekt, otevřeme si vývojové prostředí a v něm si projekt naimportujeme dle zvyklostí daného IDE. V případě IntelliJ zvolíme otevřít existující projekt a vybereme kořenovou složku projektu. IntelliJ je dostatečně chytré, aby rozpoznalo, že se jedná o Maven projekt a synchronizuje si veškeré složky.

Definice rozhraní

Začneme v modulu zdravic.api, který bude obsahovat jedno rozhraní s jednou metodou definující způsob, jak se bude uživatel zdravit. Nejdříve zde ve složce src/main/java/ založíme nový balíček s názvem cz.itnetwork.moduly.zdravic.api. V balíčku pak založíme rozhraní IZdravic s metodou pozdrav():

package cz.itnetwork.moduly.zdravic.api;

public interface IZdravic {

  String pozdrav(String jmeno);

}

Implementace rozhraní

Přesuneme se do modulu zdravic.impl a opět vytvoříme nový balíček, tentokrát s názvem cz.itnetwork.moduly.zdravic.impl. V balíčku založíme třídu ZdravicZakladni, která bude implementovat rozhraní IZdravic:

package cz.itnetwork.moduly.zdravic.impl;

import cz.itnetwork.moduly.zdravic.api.IZdravic;

public class ZdravicZakladni implements IZdravic {

  private static final String FORMAT_POZDRAVU = "Ahoj uživateli %s";

  @Override
  public String pozdrav(String jmeno) {
    return FORMAT_POZDRAVU.formatted(jmeno);
  }
}

Importem balíčku cz.itnetwork.moduly.zdravic.impl jsme vytvořili přímou závislost. IntelliJ nás upozorní, že tuto závislost musíme oznámit Mavenu. V modulu zdravic.impl tedy otevřeme konfigurační soubor pom.xml, kam přidáme Maven závislost:

<dependencies>
  <dependency>
    <groupId>cz.itnetwork.moduly</groupId>
    <artifactId>cz.itnetwork.moduly.zdravic.api</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
</dependencies>

Zadrátování

Nakonec přejdeme do posledního (hlavního) modulu a stejně jako v předchozích modulech, i zde vytvoříme nový balíček s názvem cz.itnetwork.moduly.zdravic. V něm založíme novou třídu pojmenovanou Aplikace:

package cz.itnetwork.moduly.zdravic;

import cz.itnetwork.moduly.zdravic.api.IZdravic;
import cz.itnetwork.moduly.zdravic.impl.ZdravicZakladni;

public class Aplikace {

  public static void main(String[] args) {
    IZdravic zdravicZakladni = new ZdravicZakladni();

    System.out.println(zdravicZakladni.pozdrav("Karel"));
  }
}

Aby nám zde fungovaly importy balíčků zdravic.api a zdravic.impl, musíme opět upravit Maven konfiguraci v pom.xml souboru hlavního modulu a přidat do něj závislosti na předchozích modulech:

<dependencies>
  <dependency>
    <groupId>cz.itnetwork.moduly</groupId>
    <artifactId>cz.itnetwork.moduly.zdravic.api</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
  <dependency>
    <groupId>cz.itnetwork.moduly</groupId>
    <artifactId>cz.itnetwork.moduly.zdravic.impl</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
</dependencies>

Když teď zkompilujeme celý projekt a spustíme hlavní třídu, dostaneme následující výpis:

Konzolová aplikace
Ahoj uživateli Karel

Přidání Java modulů

Nyní přišel čas na přidání Java modulů. Z předchozí lekce již víme, že moduly se zapisují do speciálním souboru module-info.java, který je umístěn v src složce daného modulu. V případě Mavenu se nachází ve složce src/main/java/.

Na následujících řádcích se bude často vyskytovat slovo modul. Někdy bude myšleno Maven modul a někdy zase Java modul. Typ bude vždy specifikován.

V Maven modulech cz.itnetwork.moduly.zdravic, cz.itnetwork.moduly.zdravic.api a cz.itnetwork.moduly.zdravic.impl založíme nové Java moduly s názvem odpovídajícím Maven modulu:

module cz.itnetwork.moduly.zdravic {
}

module cz.itnetwork.moduly.zdravic.api {
}

module cz.itnetwork.moduly.zdravic.impl {
}

Když se teď pokusíme projekt zkompilovat, tak nám kompilace neprojde a skončí s chybou:

package cz.itnetwork.moduly.zdravic.api is not visible

Otevřeme si module-info Java modulu cz.itnetwork.moduly.zdravic.api. Tento modul slouží primárně jako veřejné API. To znamená, že chceme, aby mohl rozhraní použít kdokoli. To zajistíme tím, že budeme exportovat daný balíček. V našem případě se jedná o balíček cz.itnetwork.moduly.zdravic.api. Celá definice Java modulu bude následující:

module cz.itnetwork.moduly.zdravic.api {
  exports cz.itnetwork.moduly.zdravic.api;
}

Při pokusu o kompilaci bychom opět neuspěli a uviděli bychom navíc stále stejnou chybovou hlášku. Je to logické. Rozhraní jsme "otevřeli světu". Nyní musíme udělat druhý krok a říct, který modul toto rozhraní bude používat.

Otevřeme si module-info Java modulu cz.itnetwork.moduly.zdravic.impl. Do modulu přidáme závislost na modulu cz.itnetwork.moduly.zdravic.api, zároveň exportujeme balíček cz.itnetwork.moduly.zdravic.impl. Balíček opět musíme exportovat, protože obsahuje konkrétní implementaci třídy, jejíž instanci vytváříme ve třídě Aplikace. Celá definice Java modulu bude následující:

module cz.itnetwork.moduly.zdravic.impl {
  requires cz.itnetwork.moduly.zdravic.api;
  exports cz.itnetwork.moduly.zdravic.impl;
}

Další pokus o kompilaci by vypsal chybovou hlášku, která se může zdát stejná, ale týká se jiného artefaktu:

package cz.itnetwork.moduly.zdravic.api is not visible
package cz.itnetwork.moduly.zdravic.impl is not visible

Přesuneme se tedy ještě do module-info hlavního Java modulu a přidáme závislost na modul s rozhraním a modul s implementací. Celá definice Java modulu bude následující:

module cz.itnetwork.moduly.zdravic {
  requires cz.itnetwork.moduly.zdravic.api;
  requires cz.itnetwork.moduly.zdravic.impl;
}

Konečně se nám podaří projekt zkompilovat bez žádných chyb. Když teď aplikaci spustíme, dostaneme stejný výsledek, jako když jsme ji spouštěli bez modulů:

Konzolová aplikace
Ahoj uživateli Karel

Gratuluji, právě jsme společně modularizovali základní aplikaci.

V následujícím kvízu, Kvíz - Úvod, Classloader a Moduly, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 10x (10.09 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Classloader a první modul v Javě
Všechny články v sekci
Moduly v Javě
Přeskočit článek
(nedoporučujeme)
Kvíz - Úvod, Classloader a Moduly
Článek pro vás napsal Petr Štechmüller
Avatar
Uživatelské hodnocení:
5 hlasů
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity