Skip to content

Commit

Permalink
Fix low-latency issues
Browse files Browse the repository at this point in the history
Backport more performant ClientWindowImpl
  • Loading branch information
jasondlee committed Mar 22, 2024
1 parent da1ed06 commit 35b3431
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 23 deletions.
21 changes: 21 additions & 0 deletions impl/src/main/java/com/sun/faces/context/SessionMap.java
Expand Up @@ -16,6 +16,8 @@

package com.sun.faces.context;

import static java.util.Optional.ofNullable;

import java.util.Enumeration;
import java.util.Map;
import java.util.Iterator;
Expand Down Expand Up @@ -216,4 +218,23 @@ protected HttpSession getSession(boolean createNew) {
return request.getSession(createNew);
}

// ----------------------------------------------------------- Session Mutex
private static final String MUTEX = Mutex.class.getName();

private static final class Mutex implements Serializable {
private static final long serialVersionUID = 1L;
}

public static void createMutex(HttpSession session) {
session.setAttribute(MUTEX, new Mutex());
}

public static Object getMutex(Object session) {
return session instanceof HttpSession ? ofNullable(((HttpSession) session).getAttribute(MUTEX)).orElse(session) : session;
}

public static void removeMutex(HttpSession session) {
session.removeAttribute(MUTEX);
}

} // END SessionMap
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -16,6 +16,8 @@

package com.sun.faces.lifecycle;

import com.sun.faces.config.WebConfiguration;

import javax.faces.application.Application;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
Expand All @@ -26,36 +28,22 @@
import javax.faces.lifecycle.ClientWindow;
import javax.faces.lifecycle.ClientWindowFactory;

import com.sun.faces.config.WebConfiguration;

public class ClientWindowFactoryImpl extends ClientWindowFactory {

private boolean isClientWindowEnabled = false;
private WebConfiguration config = null;
private final TokenGenerator tokenGenerator = new TokenGenerator();

public ClientWindowFactoryImpl() {
super(null);
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().subscribeToEvent(PostConstructApplicationEvent.class,
Application.class, new PostConstructApplicationListener());
context.getApplication().subscribeToEvent(PostConstructApplicationEvent.class, Application.class, new PostConstructApplicationListener());
}

public ClientWindowFactoryImpl(boolean ignored) {
super(null);
isClientWindowEnabled = false;
}


@Override
public ClientWindow getClientWindow(FacesContext context) {
if (!isClientWindowEnabled) {
return null;
}

return new ClientWindowImpl(tokenGenerator);
}

private class PostConstructApplicationListener implements SystemEventListener {

@Override
Expand All @@ -78,4 +66,13 @@ private void postConstructApplicationInitialization() {

isClientWindowEnabled = null != optionValue && "url".equals(optionValue);
}

@Override
public ClientWindow getClientWindow(FacesContext context) {
if (!isClientWindowEnabled) {
return null;
}

return new ClientWindowImpl();
}
}
15 changes: 8 additions & 7 deletions impl/src/main/java/com/sun/faces/lifecycle/ClientWindowImpl.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -16,9 +16,12 @@

package com.sun.faces.lifecycle;

import static com.sun.faces.context.SessionMap.getMutex;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.CLIENT_WINDOW_PARAM;

import java.util.Map;
import java.util.UUID;

import javax.faces.component.UINamingContainer;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
Expand All @@ -27,11 +30,9 @@

public class ClientWindowImpl extends ClientWindow {

private final TokenGenerator tokenGenerator;
String id;

public ClientWindowImpl(TokenGenerator tokenGenerator) {
this.tokenGenerator = tokenGenerator;
public ClientWindowImpl() {
}

@Override
Expand All @@ -56,7 +57,7 @@ public void decode(FacesContext context) {
}

private String calculateClientWindow(FacesContext context) {
synchronized (context.getExternalContext().getSession(true)) {
synchronized (getMutex(context.getExternalContext().getSession(true))) {
final String clientWindowCounterKey = "com.sun.faces.lifecycle.ClientWindowCounterKey";
ExternalContext extContext = context.getExternalContext();
Map<String, Object> sessionAttrs = extContext.getSessionMap();
Expand All @@ -65,9 +66,9 @@ private String calculateClientWindow(FacesContext context) {
counter = Integer.valueOf(0);
}
char sep = UINamingContainer.getSeparatorChar(context);
id = tokenGenerator.getNextToken() + sep + ++counter;
id = UUID.randomUUID().toString() + sep + +counter;

sessionAttrs.put(clientWindowCounterKey, counter);
sessionAttrs.put(clientWindowCounterKey, ++counter);
}
return id;
}
Expand Down

0 comments on commit 35b3431

Please sign in to comment.