Redis - Lab 3
This lab will introduce an entity integration with Redis database with Java.
1. Create an entity
Steps
- Create a class called
Userin theexpert.os.labs.persistencepackage - Annotate this class with
@Entity, indicating that it's a persistent entity -
Add the following
privatefields with its typestype field StringuserNameStringnameMap<String, String>settingsSet<String>languages -
Annotate the
userNamewith@Idfrom thejakarta.nosqlpackage - Create a constructor using all fields
- Create get methods for each field
- Add the
toString()method
Expected results
- Entity
Usercreated
Solution
Click to see...
import jakarta.nosql.Entity;
import jakarta.nosql.Id;
import java.util.Map;
import java.util.Set;
@Entity
public class User {
@Id
private String userName;
private String name;
private Map<String, String> settings;
private Set<String> languages;
public User() {
}
public User(String userName, String name, Map<String, String> settings, Set<String> languages) {
this.userName = userName;
this.name = name;
this.settings = settings;
this.languages = languages;
}
public String getUserName() {
return userName;
}
public String getName() {
return name;
}
public Map<String, String> getSettings() {
return settings;
}
public Set<String> getLanguages() {
return languages;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", name='" + name + '\'' +
", settings=" + settings +
", languages=" + languages +
'}';
}
}
2. Implement the Builder class
Steps
- Create a class called
UserBuilderin theexpert.os.labs.persistencepackage - Add the same fields we had previously added to the
Userclass, without the annotations -
Add the builder methods for each field
-
example using the
userNamefield
-
-
Add the
build()method creating a new instance ofUserusing its constructor -
In the
Userclass add the builder method referring to theUserBuilder
Expected results
- A new
UserBuilderclass implementing the Builder pattern for theUserclass - A new
builder()method in theUserclass
Solution
Click to see...
import java.util.Collections;
import java.util.Map;
import java.util.Set;
public class UserBuilder {
private String username;
private String name;
private Map<String, String> settings = Collections.emptyMap();
private Set<String> languages = Collections.emptySet();
public UserBuilder username(String username) {
this.username = username;
return this;
}
public UserBuilder name(String name) {
this.name = name;
return this;
}
public UserBuilder settings(Map<String, String> settings) {
this.settings = settings;
return this;
}
public UserBuilder languages(Set<String> languages) {
this.languages = languages;
return this;
}
public User build() {
return new User(username, name, settings, languages);
}
}
3. Define the repository interface
- Create an
interfacecalledUserRepositoryin theexpert.os.labs.persistencepackage - Annotate the class with
@Repositoryfrom thejakarta.data.repositorypackage extendsthe class usingCrudRepository<User, String>from thejakarta.data.repositorypackage
Expected results
- The
UserRepositorythat specifies methods for performing CRUD (Create, Read, Update, Delete) operations onUserentities
Solution
Click to see...
4. Create the execution class
Steps
- Create a class called
AppUserin theexpert.os.labs.persistencepackage -
Add a main method
-
Set up a try-with-resources block, inside the
mainmethod, to manage the Jakarta EESeContainerthat is responsible for dependency injection and managing resources -
Obtain an instance of the
KeyValueTemplateto interact with the key-value store -
Create two user instances using the builder from the
Userclass with different data inside thetrystatementUser user1 = User.builder().username("user1").name("Otavio Santana") .languages(Set.of("Portuguese", "English", "Spanish", "Italian", "French")) .settings(Map.of("location", "Portugal", "currency", "EUR")).build(); User user2 = User.builder().username("user2").name("Poliana Santana") .languages(Set.of("Portuguese", "English")) .settings(Map.of("location", "Portugal", "currency", "EUR")).build(); -
Add the two user instances into the key-value store using the
KeuValueTemplate, where the second one will have a delay of 1 second -
Retrieve the
user2data based on itsuserNameand printout the result- use the method
get()from thetemplatefield - the first parameter is the value of the
userNamefield and the second parameter is the class
- use the method
-
Add a wait time, then retrieve and printout the same user again
-
Retrieve the
user1data based on itsuserNameand printout the result -
Define a private constructor for the
AppUserclass to prevent instantiation since it contains only static methods: -
Run the
main()method
Expected results
-
The following output
User2 data: Optional[User{userName='user2', name='Poliana Santana', settings={location=Portugal, currency=EUR}, languages=[English, Portuguese]}] User2 second retrieve data: Optional.empty User1 data: Optional[User{userName='user1', name='Otavio Santana', settings={location=Portugal, currency=EUR}, languages=[English, Italian, French, Portuguese, Spanish]}] -
The second printout, related to the
user2does not show any data because it expired
Solution
Click to see...
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import jakarta.nosql.keyvalue.KeyValueTemplate;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class AppUser {
public static void main(String[] args) throws InterruptedException {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
KeyValueTemplate template = container.select(KeyValueTemplate.class).get();
User user1 = User.builder().username("user1").name("Otavio Santana")
.languages(Set.of("Portuguese", "English", "Spanish", "Italian", "French"))
.settings(Map.of("location", "Portugal", "currency", "EUR")).build();
User user2 = User.builder().username("user2").name("Poliana Santana")
.languages(Set.of("Portuguese", "English"))
.settings(Map.of("location", "Portugal", "currency", "EUR")).build();
template.put(user1);
template.put(user2, Duration.ofSeconds(1));
Optional<User> user2Data = template.get("user2", User.class);
System.out.println("User2 data: " + user2Data);
TimeUnit.SECONDS.sleep(2L);
Optional<User> user2DataSecondRetrieve = template.get("user2", User.class);
System.out.println("User2 second retrieve data: " + user2DataSecondRetrieve);
Optional<User> user1Data = template.get("user1", User.class);
System.out.println("User1 data: " + user1Data);
}
}
}
5. Use the UserRepository with Redis
Steps
- Create an interface called
UserRepositoryin theexpert.os.labs.persistencepackage - Annotate the class with
@Repositoryfrom thejakarta.data.repositorypackage -
Extends the interface using the
CrudRepository
Expected results
- The integration in Redis with the repository to perform the CRUD operations in the
Userentity
Solution
Click to see...
6. Using the UserRepository
Steps
- Create a class called
AppRepositoryin theexpert.os.labs.persistencepackage -
Add a main method
-
Set up a try-with-resources block, inside the
mainmethod, to manage the Jakarta EESeContainerthat is responsible for dependency injection and managing resources -
Add the
UserRepositoryinstance -
Create a new
Userobject -
Save the
Userobject -
Retrieve the
Userobject saved by its id, which isusername, using thefindByIdmethod from the repository and printout the result -
Check if a user already exists using the
existsByIdmethod from the repository, and printout the result -
Delete the user using the
deleteByIdmethod -
Check if a user still exists using the
existsByIdmethod from the repository, and printout the result -
Define a private constructor for the
AppRepositoryclass to prevent instantiation since it contains only static methods: -
Run the
main()method
Expected results
-
The following output
Solution
Click to see...
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class AppRepository {
public static void main(String[] args) {
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
UserRepository repository = container.select(UserRepository.class).get();
User ada = User.builder().username("ada").name("Ada Lovelace")
.languages(Set.of("Latin")).settings(Map.of("currency", "food")).build();
repository.save(ada);
Optional<User> userFound = repository.findById("ada");
System.out.println(userFound);
boolea userExist = repository.existsById("ada");
System.out.println("userExist? = " + userExist);
repository.deleteById("ada");
userExist = repository.existsById("ada");
System.out.println("userExist? = " + userExist);
}
}
private AppRepository() {
}
}