Jakarta CDI - Lab 1 - Basic part 2
In this lab, we will explore using CDI qualifiers to work when there are several implementations of a single interface.
1. Define an instrument
Steps
- Open the
01-jakarta-ee
project and navigate to thesrc/main/java
- Create an
interface
calledInstrument
in theexpert.os.labs.persistence.cid.music
package - Add a
sound()
method that returnsString
Expected results
- Interface
Instrument
that will produce asound()
for the later instrument types
Solution
2. Define the instrument types
Steps
- Create an
enum
calledInstrumentType
in theexpert.os.labs.persistence.cid.music
package - Add the following constants, related to the different musical instrument types:
STRING
PERCUSSION
KEYBOARD
Expected results
- Enum
InstrumentType
created in thesrc/main/java
at theexpert.os.labs.persistence.cdi.music
Solution
3. Create a custom Qualifier Annotation (the musical instruments)
The annotated class will represent musical instruments and specify the instrument type.
Steps
- Create an
@interface
calledMusicalInstrument
in theexpert.os.labs.persistence.cid.music
package -
Add the following code:
import jakarta.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface MusicalInstrument { InstrumentType value(); }
-
Define different musical instruments (classes), implementing the
Instrument
interface:- the classes must be created at the
expert.os.labs.persistence.cid.music
package - use the
jakarta.enterprise.inject
package to import the@Default
annotation
Class Annotation sound Piano
@MusicalInstrument(InstrumentType.KEYBOARD)
and@Default
return "piano"
Violin
@MusicalInstrument(InstrumentType.STRING)
return "violin"
Xylophone
@MusicalInstrument(InstrumentType.PERCUSSION)
return "xylophone"
- the classes must be created at the
Expected results
- Three classes (
Piano
,Violin
, andXylophone
) represent different musical instruments and are annotated withMusicalInstrument
to specify their instrument types. @Default
annotation is used on thePiano
class, indicating it as the default implementation for theInstrument
interface.
Solution
Click to see...
Piano class
import jakarta.enterprise.inject.Default;
@MusicalInstrument(InstrumentType.KEYBOARD)
@Default
class Piano implements Instrument {
@Override
public String sound() {
return "piano";
}
}
Violin class
@MusicalInstrument(InstrumentType.STRING)
class Violin implements Instrument {
@Override
public String sound() {
return "violin";
}
}
Xylophone class
4. Create the orchestra
The Orchestra
class represents an orchestra and is annotated with @ApplicationScoped
, indicating that there will be a single instance of this class per application.
It contains fields for different types of musical instruments (percussion
, keyboard
, string
, and solo
) and an Instance<Instrument>
to handle multiple instrument instances.
The class includes methods to play specific types of instruments (string()
, percussion()
, keyboard()
), play a solo instrument (solo()
), and play all available instruments (allSound()
).
Steps
- Create a class called
Orchestra
in theexpert.os.labs.persistence.cid.music
package - Annotate the class with
@ApplicationScoped
from thejakarta.enterprise.context
package -
Add a logger for this class
-
Add the following
Instrument
fields with the related annotationsField name Annotation 1 Annotation 2 percussion
@Inject
@MusicalInstrument(InstrumentType.PERCUSSION)
keyboard
@Inject
@MusicalInstrument(InstrumentType.KEYBOARD)
string
@Inject
@MusicalInstrument(InstrumentType.STRING)
solo
@Inject
-
Add the
Instrument
instance as a new field as follows: -
Add the following methods, that are related to each instrument type
-
Add a method to list all sounds
Expected results
- Class
Orchestra
that can call any musical instrument to play
Solution
Click to see...
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@ApplicationScoped
public class Orchestra {
private static final Logger LOGGER = Logger.getLogger(Orchestra.class.getName());
@Inject
@MusicalInstrument(InstrumentType.PERCUSSION)
private Instrument <;
@Inject
@MusicalInstrument(InstrumentType.KEYBOARD)
private Instrument keyboard;
@Inject
@MusicalInstrument(InstrumentType.STRING)
private Instrument string;
@Inject
private Instrument solo;
@Inject
@Any
private Instance<Instrument> instruments;
public void string() {
LOGGER.info("The string's sound: " + this.string.sound());
}
public void percussion() {
LOGGER.info("The percussion's sound: " + this.percussion.sound());
}
public void keyboard() {
LOGGER.info("The keyboard's sound: " + this.keyboard.sound());
}
public void solo() {
LOGGER.info("The solo's sound: " + this.keyboard.sound());
}
public void allSound() {
String sounds = this.instruments.stream().map(Instrument::sound).collect(Collectors.joining(", "));
LOGGER.info("All instruments sounds are: " + sounds);
}
}
5. Explore the class usage
Steps
- Create a class called
AppOrchestra
in theexpert.os.labs.persistence.cid
package -
Add the following code to the class
import expert.os.labs.persistence.persistence.cdi.music.Orchestra; import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; public class App2 { public static void main(String[] args) { try (SeContainer container = SeContainerInitializer.newInstance().initialize()) { Orchestra orchestra = container.select(Orchestra.class).get(); orchestra.percussion(); orchestra.keyboard(); orchestra.string(); orchestra.solo(); orchestra.allSound(); } } }
-
Run the class
Expected results
-
List of
INFO
messages related to each instrument called by the Orchestra
Solution
Click to see...
import expert.os.labs.persistence.persistence.cdi.music.Orchestra;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
public class AppOrchestra {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
Orchestra orchestra = container.select(Orchestra.class).get();
orchestra.percussion();
orchestra.keyboard();
orchestra.string();
orchestra.solo();
orchestra.allSound();
}
}
}