import project

This commit is contained in:
Fabio Scotto di Santolo
2023-10-01 14:26:53 +02:00
parent 007b7f2dcc
commit 82e0977599
30 changed files with 2066 additions and 1 deletions

View File

@@ -0,0 +1,11 @@
package org.acme;
import java.io.Serializable;
public interface CollectEvent extends Serializable {
Type getType();
enum Type {
CREATION, UPDATE, DELETE;
}
}

View File

@@ -0,0 +1,30 @@
package org.acme;
import jakarta.enterprise.context.RequestScoped;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
@RequestScoped
public class EventCollector {
private final Map<String, Collection<CollectEvent>> cache;
public EventCollector() {
cache = new HashMap<>();
}
public void register(String type, CollectEvent event) {
if (!cache.containsKey(type)) {
cache.put(type, new ArrayList<>());
}
cache.get(type).add(event);
}
public Stream<CollectEvent> stream(String type) {
return cache.get(type).stream();
}
}

View File

@@ -0,0 +1,16 @@
package org.acme;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class ExampleResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from RESTEasy Reactive";
}
}

View File

@@ -0,0 +1,32 @@
package org.acme;
import io.quarkus.runtime.Startup;
import jakarta.enterprise.context.ApplicationScoped;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.jboss.logging.Logger;
@Startup
@ApplicationScoped
public class HibernateEventListenerIntegrator implements Integrator {
private final Logger log = Logger.getLogger(HibernateEventListenerIntegrator.class);
@Override
public void integrate(Metadata metadata, BootstrapContext bootstrapContext, SessionFactoryImplementor sessionFactory) {
log.info("Integrate registry");
EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.appendListeners(EventType.POST_COMMIT_INSERT, UserEventListener.class);
registry.appendListeners(EventType.POST_COMMIT_UPDATE, UserEventListener.class);
registry.appendListeners(EventType.POST_COMMIT_DELETE, UserEventListener.class);
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactoryImplementor, SessionFactoryServiceRegistry sessionFactoryServiceRegistry) {
}
}

View File

@@ -0,0 +1,63 @@
package org.acme;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import java.util.Objects;
@Entity
@Table(name = "users")
public class User extends PanacheEntity {
@Column(name = "name", unique = true)
private String name;
@Column(name = "passwd")
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(getId(), user.getId()) && Objects.equals(getName(), user.getName()) && Objects.equals(getPassword(), user.getPassword());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getName(), getPassword());
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}

View File

@@ -0,0 +1,52 @@
package org.acme;
import java.time.LocalDateTime;
import java.util.Objects;
public class UserCreated implements CollectEvent {
private String username;
private LocalDateTime timestamp;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
@Override
public CollectEvent.Type getType() {
return Type.CREATION;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserCreated that = (UserCreated) o;
return Objects.equals(getUsername(), that.getUsername()) && Objects.equals(getTimestamp(), that.getTimestamp());
}
@Override
public int hashCode() {
return Objects.hash(getUsername(), getTimestamp());
}
@Override
public String toString() {
return "UserCreated{" +
"username='" + username + '\'' +
", timestamp=" + timestamp +
'}';
}
}

View File

@@ -0,0 +1,46 @@
package org.acme;
import java.util.Objects;
public class UserDTO {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDTO userDTO = (UserDTO) o;
return Objects.equals(getName(), userDTO.getName()) && Objects.equals(getPassword(), userDTO.getPassword());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getPassword());
}
@Override
public String toString() {
return "UserDTO{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}

View File

@@ -0,0 +1,52 @@
package org.acme;
import java.time.LocalDateTime;
import java.util.Objects;
public class UserDeleted implements CollectEvent {
private long id;
private LocalDateTime timestamp;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
@Override
public CollectEvent.Type getType() {
return Type.DELETE;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDeleted that = (UserDeleted) o;
return getId() == that.getId() && Objects.equals(getTimestamp(), that.getTimestamp());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getTimestamp());
}
@Override
public String toString() {
return "UserDeleted{" +
"id=" + id +
", timestamp=" + timestamp +
'}';
}
}

View File

@@ -0,0 +1,72 @@
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.hibernate.event.spi.*;
import org.hibernate.persister.entity.EntityPersister;
import org.jboss.logging.Logger;
import java.util.List;
import java.util.stream.Collectors;
@ApplicationScoped
public class UserEventListener implements PostCommitInsertEventListener, PostCommitUpdateEventListener, PostCommitDeleteEventListener {
private final Logger log = Logger.getLogger(UserEventListener.class);
private final EventCollector eventCollector;
@Inject
public UserEventListener(EventCollector eventCollector) {
this.eventCollector = eventCollector;
}
@Override
public void onPostInsert(PostInsertEvent postInsertEvent) {
log.info("onPostInsert called");
List<CollectEvent> events = eventCollector.stream(User.class.getCanonicalName())
.filter(it -> it.getType() == CollectEvent.Type.CREATION)
.collect(Collectors.toUnmodifiableList());
log.info("fire " + events.size() + " events");
}
@Override
public void onPostUpdate(PostUpdateEvent postUpdateEvent) {
log.info("onPostUpdate called");
List<CollectEvent> events = eventCollector.stream(User.class.getCanonicalName())
.filter(it -> it.getType() == CollectEvent.Type.UPDATE)
.collect(Collectors.toUnmodifiableList());
log.info("fire " + events.size() + " events");
}
@Override
public void onPostDelete(PostDeleteEvent postDeleteEvent) {
log.info("onPostDelete called");
List<CollectEvent> events = eventCollector.stream(User.class.getCanonicalName())
.filter(it -> it.getType() == CollectEvent.Type.DELETE)
.collect(Collectors.toUnmodifiableList());
log.info("fire " + events.size() + " events");
}
@Override
public boolean requiresPostCommitHandling(EntityPersister entityPersister) {
return true;
}
@Override
public void onPostDeleteCommitFailed(PostDeleteEvent postDeleteEvent) {
log.info("onPostDeleteCommitFailed called");
}
@Override
public void onPostInsertCommitFailed(PostInsertEvent postInsertEvent) {
log.info("onPostInsertCommitFailed called");
}
@Override
public void onPostUpdateCommitFailed(PostUpdateEvent postUpdateEvent) {
log.info("onPostUpdateCommitFailed called");
}
}

View File

@@ -0,0 +1,30 @@
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.event.TransactionPhase;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;
@ApplicationScoped
public class UserObserver {
private final Logger log = Logger.getLogger(UserObserver.class);
private final EventCollector eventCollector;
@Inject
public UserObserver(EventCollector eventCollector) {
this.eventCollector = eventCollector;
}
public void onCreation(@Observes(during = TransactionPhase.AFTER_SUCCESS) UserCreated event) {
log.info("Arrived event for user " + event.getUsername());
eventCollector.register(User.class.getCanonicalName(), event);
}
public void onDelete(@Observes(during = TransactionPhase.AFTER_SUCCESS) UserDeleted event) {
log.info("Arrived event for deletion user " + event.getId());
eventCollector.register(User.class.getCanonicalName(), event);
}
}

View File

@@ -0,0 +1,37 @@
package org.acme;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import java.util.Collection;
@Path(("/users"))
public class UserResource {
private final UserService userService;
@Inject
public UserResource(UserService userService) {
this.userService = userService;
}
@GET
public Response users() {
Collection<UserDTO> users = userService.getUsers();
return Response.ok(users).build();
}
@POST
public Response createUser(@RequestBody UserDTO user) {
userService.createUser(user);
return Response.ok().build();
}
@DELETE
@Path("/{id}")
public Response deleteUser(@PathParam("id") Long id) {
userService.deleteUser(id);
return Response.ok().build();
}
}

View File

@@ -0,0 +1,64 @@
package org.acme;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Event;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.jboss.logging.Logger;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.stream.Collectors;
@ApplicationScoped
public class UserService {
private final Logger log = Logger.getLogger(UserService.class);
private final Event<CollectEvent> collectEventSender;
@Inject
public UserService(Event<CollectEvent> collectEventSender) {
this.collectEventSender = collectEventSender;
}
public Collection<UserDTO> getUsers() {
return User.<User>findAll()
.stream()
.map(it -> {
UserDTO userDTO = new UserDTO();
userDTO.setName(it.getName());
userDTO.setPassword(it.getPassword());
return userDTO;
})
.collect(Collectors.toList());
}
@Transactional
public void createUser(UserDTO user) {
User userEntity = new User();
userEntity.setName(user.getName());
userEntity.setPassword(user.getPassword());
UserCreated userCreated = new UserCreated();
userCreated.setUsername(userEntity.getName());
userCreated.setTimestamp(LocalDateTime.now());
log.info("Creation event fired");
collectEventSender.fire(userCreated);
User.persist(userEntity);
log.info("Created user " + user.getName());
}
@Transactional
public void deleteUser(Long id) {
UserDeleted userDeleted = new UserDeleted();
userDeleted.setId(id);
userDeleted.setTimestamp(LocalDateTime.now());
log.info("Delete event fired");
collectEventSender.fire(userDeleted);
User.deleteById(id);
log.info("Deleted user with id " + id);
}
}