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...
1 parent 625ed0d commit 8dbd495005c2488b5adc4d06bb3b57d5fc561607 @BalusC BalusC committed Mar 24, 2016
@@ -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 =
@@ -230,11 +242,43 @@ 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.