Permalink
Browse files

#199: fix failing view scope unload when bean is constructed for first

time during postback on same view (i.e. not on initial request; this is
unusual but not impossible). For this, added Ajax#load().
  • Loading branch information...
BalusC committed Mar 24, 2016
1 parent 625ed0d commit 8dbd495005c2488b5adc4d06bb3b57d5fc561607
@@ -16,6 +16,7 @@
package org.omnifaces.cdi.viewscope;
import static java.lang.Boolean.TRUE;
import static org.omnifaces.util.Ajax.load;
import static org.omnifaces.util.Ajax.oncomplete;
import static org.omnifaces.util.Components.addScriptResourceToBody;
import static org.omnifaces.util.Components.addScriptResourceToHead;
@@ -233,17 +234,23 @@ private void createViewScope(UUID id) {
activeViewScopes.put(id, new BeanStorage(DEFAULT_BEANS_PER_VIEW_SCOPE));
FacesContext context = FacesContext.getCurrentInstance();
boolean ajaxRequestWithPartialRendering = isAjaxRequestWithPartialRendering(context);
if (context.getCurrentPhaseId() != PhaseId.RENDER_RESPONSE || TRUE.equals(context.getAttributes().get(StateManager.IS_BUILDING_INITIAL_STATE))) {
addScriptResourceToHead("omnifaces", "omnifaces.js");
}
else if (!Hacks.isScriptResourceRendered(context, new ResourceIdentifier("omnifaces", "omnifaces.js"))) {
addScriptResourceToBody("omnifaces", "unload.js");
if (!Hacks.isScriptResourceRendered(context, new ResourceIdentifier("omnifaces", "omnifaces.js"))) {
if (ajaxRequestWithPartialRendering) {
load("omnifaces", "unload.js");
}
else if (context.getCurrentPhaseId() != PhaseId.RENDER_RESPONSE || TRUE.equals(context.getAttributes().get(StateManager.IS_BUILDING_INITIAL_STATE))) {
addScriptResourceToHead("omnifaces", "omnifaces.js");
}
else {
addScriptResourceToBody("omnifaces", "unload.js");
}
}
String script = String.format(SCRIPT_INIT, id);
if (isAjaxRequestWithPartialRendering(context)) {
if (ajaxRequestWithPartialRendering) {
oncomplete(script);
}
else {
@@ -12,15 +12,22 @@
*/
package org.omnifaces.util;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.omnifaces.util.Components.getCurrentComponent;
import static org.omnifaces.util.Components.getCurrentForm;
import static org.omnifaces.util.Faces.getApplication;
import static org.omnifaces.util.Faces.isAjaxRequestWithPartialRendering;
import java.beans.Introspector;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import javax.faces.FacesException;
import javax.faces.application.Resource;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
@@ -59,6 +66,11 @@
// Constants ------------------------------------------------------------------------------------------------------
private static final String ERROR_NO_SCRIPT_RESOURCE =
"";
private static final String ERROR_NO_PARTIAL_RENDERING =
"The current request is not an ajax request with partial rendering."
+ " Use Components#addScriptXxx() methods instead.";
private static final String ERROR_ARGUMENTS_LENGTH =
"The arguments length must be even. Encountered %d items.";
private static final String ERROR_ARGUMENT_TYPE =
@@ -229,12 +241,44 @@ private static void updateColumnCells(UIData table, int index, int rowCount) {
}
}
/**
* Load given script resource on complete of the current ajax response. Basically, it loads the script resource as
* a {@link String} and then delegates it to {@link #oncomplete(String...)}.
* @param libraryName Library name of the JavaScript resource.
* @param resourceName Resource name of the JavaScript resource.
* @throws IllegalArgumentException When given script resource cannot be found.
* @throws IllegalStateException When current request is not an ajax request with partial rendering. You should use
* either {@link Components#addScriptResourceToBody(String, String)}
* or {@link Components#addScriptResourceToHead(String, String)} instead.
* @since 2.3
*/
public static void load(String libraryName, String resourceName) {
Resource resource = getApplication().getResourceHandler().createResource(resourceName, libraryName);
if (resource == null) {
throw new IllegalArgumentException(ERROR_NO_SCRIPT_RESOURCE);
}
try (Scanner scanner = new Scanner(resource.getInputStream(), UTF_8.name())) {
oncomplete(scanner.useDelimiter("\\A").next());
}
catch (IOException e) {
throw new FacesException(e);
}
}
/**
* Execute the given scripts on complete of the current ajax response.
* @param scripts The scripts to be executed.
* @throws IllegalStateException When current request is not an ajax request with partial rendering. You should use
* {@link Components#addScriptToBody(String)} instead.
* @see OmniPartialViewContext#addCallbackScript(String)
*/
public static void oncomplete(String... scripts) {
if (!isAjaxRequestWithPartialRendering()) {
throw new IllegalStateException(ERROR_NO_PARTIAL_RENDERING);
}
OmniPartialViewContext context = OmniPartialViewContext.getCurrentInstance();
for (String script : scripts) {
@@ -115,6 +115,7 @@ public UIViewRoot restoreView(FacesContext context, String viewId) {
private boolean restoreViewRootState(FacesContext context, ResponseStateManager manager, UIViewRoot view) {
Object state = manager.getState(context, view.getViewId());
// TODO: this assumes partial state saving not full state saving (thus doesn't work on full state saving).
if (state == null || !(state instanceof Object[]) || ((Object[]) state).length < 2 || !(((Object[]) state)[1] instanceof Map)) {
return false;
}

0 comments on commit 8dbd495

Please sign in to comment.