Skip to content

Commit

Permalink
Fix #291: Prevent duplicate growl messages
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Jul 8, 2023
1 parent 20e950a commit b8ae311
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 61 deletions.
36 changes: 13 additions & 23 deletions src/main/java/org/primefaces/showcase/domain/Book.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
*/
package org.primefaces.showcase.domain;

import java.io.Serializable;

import io.quarkus.runtime.annotations.RegisterForReflection;

import java.io.Serializable;
import java.util.Objects;

@RegisterForReflection
public class Book implements Serializable {

Expand Down Expand Up @@ -69,27 +70,16 @@ public void setPages(Integer pages) {
this.pages = pages;
}

public int hashCode() {
int hash = 1;
if (title != null) {
hash = hash * 31 + title.hashCode();
}

if (author != null) {
hash = hash * 29 + author.hashCode();
}

return hash;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(title, book.title) && Objects.equals(author, book.author);
}

public boolean equals(Object obj) {
if (!(obj instanceof Book)) {
return false;
}

Book book = (Book) obj;

return (book.getTitle() != null && book.getTitle().equals(title)) &&
(book.getAuthor() != null && book.getAuthor().equals(author));
@Override
public int hashCode() {
return Objects.hash(title, author);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import jakarta.faces.event.PhaseListener;

import java.io.Serial;
import java.util.ArrayList;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Enables messages to be rendered on different pages from which they were set.
Expand All @@ -37,24 +39,24 @@ public class MultiPageMessagesSupport implements PhaseListener {

@Serial
private static final long serialVersionUID = 1250469273857785274L;
private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";
private static final String TOKEN = "MULTI_PAGE_MESSAGES_SUPPORT";

public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}

/*
* Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
* have arrived here and the response is already complete, then the page is
* not going to show up: don't display messages yet.
*/
public void beforePhase(final PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();
this.saveMessages(facesContext);
this.saveMessages(facesContext, facesContext.getExternalContext().getSessionMap());

if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
/*
* Check to see if we are "naturally" in the RENDER_RESPONSE phase. If
* we have arrived here and the response is already complete, then the
* page is not going to show up: don't display messages yet.
*/
if (!facesContext.getResponseComplete()) {
this.restoreMessages(facesContext);
this.restoreMessages(facesContext, facesContext.getExternalContext().getSessionMap());
}
}
}
Expand All @@ -65,49 +67,75 @@ public void beforePhase(final PhaseEvent event) {
public void afterPhase(final PhaseEvent event) {
if (!PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
FacesContext facesContext = event.getFacesContext();
this.saveMessages(facesContext);
this.saveMessages(facesContext, facesContext.getExternalContext().getSessionMap());
}
}

@SuppressWarnings("unchecked")
private int saveMessages(final FacesContext facesContext) {
List<FacesMessage> messages = new ArrayList<>();
for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext(); ) {
messages.add(iter.next());
iter.remove();
}
public void saveMessages(final FacesContext facesContext, final Map<String, Object> destination) {
if (facesContext != null) {
Set<FacesMessageWrapper> messages = new LinkedHashSet<>();
for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext(); ) {
messages.add(new FacesMessageWrapper(iter.next()));
}

if (messages.size() == 0) {
return 0;
if (messages.size() > 0) {
Set<FacesMessageWrapper> existingMessages = (LinkedHashSet<FacesMessageWrapper>) destination.get(TOKEN);
if (existingMessages != null) {
existingMessages.addAll(messages);
} else {
destination.put(TOKEN, messages);
}
}
}
}

@SuppressWarnings("unchecked")
public void restoreMessages(final FacesContext facesContext, final Map<String, Object> source) {
if (facesContext != null) {
// get save messages from the session
Set<FacesMessageWrapper> messages = (LinkedHashSet<FacesMessageWrapper>) source.remove(TOKEN);

Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> existingMessages = (List<FacesMessage>) sessionMap.get(sessionToken);
if (existingMessages != null) {
for (FacesMessage fm : messages) {
if (!existingMessages.contains(fm)) {
existingMessages.add(fm);
// nothing to do
if (messages == null) {
return;
}

// build set of message currently in the FacesContext
Set<FacesMessageWrapper> exitingMessages = new LinkedHashSet<>();
for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext(); ) {
exitingMessages.add(new FacesMessageWrapper(iter.next()));
}

// restore all messages not already in the FacesContext
for (FacesMessageWrapper message : messages) {
if (!exitingMessages.contains(message)) {
facesContext.addMessage(null, message.wrapped());
}
}
} else {
sessionMap.put(sessionToken, messages);

}
return messages.size();
}

@SuppressWarnings("unchecked")
private int restoreMessages(final FacesContext facesContext) {
Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> messages = (List<FacesMessage>) sessionMap.remove(sessionToken);
private record FacesMessageWrapper(FacesMessage wrapped) implements Serializable {

if (messages == null) {
return 0;
@Serial
private static final long serialVersionUID = 1L;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FacesMessageWrapper other = (FacesMessageWrapper) o;
return Objects.equals(wrapped.getSeverity(), other.wrapped().getSeverity()) &&
Objects.equals(wrapped.getSummary(), other.wrapped().getSummary()) &&
Objects.equals(wrapped.getDetail(), other.wrapped().getDetail());
}

int restoredCount = messages.size();
for (FacesMessage element : messages) {
facesContext.addMessage(null, element);
@Override
public int hashCode() {
return Objects.hash(wrapped.getSeverity(), wrapped.getSummary(), wrapped.getDetail());
}
return restoredCount;

}
}

0 comments on commit b8ae311

Please sign in to comment.