Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow disable component tracker #18355

Merged
merged 3 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.vaadin.flow.component.Component;
import com.vaadin.flow.router.internal.AbstractNavigationStateRenderer;
import com.vaadin.flow.server.AbstractConfiguration;
import com.vaadin.flow.server.InitParameters;
import com.vaadin.flow.server.VaadinContext;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.startup.ApplicationConfiguration;
Expand All @@ -45,7 +46,7 @@ public class ComponentTracker {
private static Map<Component, Location> attachLocation = Collections
.synchronizedMap(new WeakHashMap<>());

private static Boolean productionMode = null;
private static Boolean disabled = null;
private static String[] prefixesToSkip = new String[] {
"com.vaadin.flow.component.", "com.vaadin.flow.di.",
"com.vaadin.flow.dom.", "com.vaadin.flow.internal.",
Expand Down Expand Up @@ -159,7 +160,7 @@ public static Location findCreate(Component component) {
* the component to track
*/
public static void trackCreate(Component component) {
if (isProductionMode()) {
if (isDisabled()) {
return;
}
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Expand Down Expand Up @@ -192,7 +193,7 @@ public static Location findAttach(Component component) {
* the component to track
*/
public static void trackAttach(Component component) {
if (isProductionMode()) {
if (isDisabled()) {
return;
}
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Expand Down Expand Up @@ -270,17 +271,22 @@ private static Location findRelevantLocation(
}

/**
* Checks if the application is running in production mode.
* Checks if the component tracking is disabled.
*
* Tracking is disabled when application is running in production mode or if
* the configuration property
* {@literal vaadin.devmode.componentTracker.enabled} is set to
* {@literal false}.
*
* When unsure, reports that production mode is true so tracking does not
* take place in production.
*
* @return true if in production mode or the mode is unclear, false if in
* development mode
**/
private static boolean isProductionMode() {
if (productionMode != null) {
return productionMode;
private static boolean isDisabled() {
if (disabled != null) {
return disabled;
}

VaadinService service = VaadinService.getCurrent();
Expand All @@ -300,8 +306,11 @@ private static boolean isProductionMode() {
return true;
}

productionMode = applicationConfiguration.isProductionMode();
return productionMode;
disabled = applicationConfiguration.isProductionMode()
|| !applicationConfiguration.getBooleanProperty(
InitParameters.APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER,
true);
return disabled;
}

private static Location toLocation(StackTraceElement stackTraceElement) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ public class InitParameters implements Serializable {
*/
public static final String APPLICATION_PARAMETER_DEVMODE_ENABLE_SERIALIZE_SESSION = "devmode.sessionSerialization.enabled";

/**
* Configuration parameter name for enabling component tracking in
* development mode. If not set, tracking is enabled by default.
*
* @since
*/
public static final String APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER = "devmode.componentTracker.enabled";

/**
* I18N provider property.
*/
Expand Down
31 changes: 15 additions & 16 deletions flow-server/src/test/java/com/vaadin/flow/ComponentTrackerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,20 @@ public Layout(Component... components) {
}
}

private Object previousProdMode;
private Field prodModeField;
private Object previousDisabled;
private Field disabledField;

@Before
public void setup() throws Exception {
prodModeField = ComponentTracker.class
.getDeclaredField("productionMode");
prodModeField.setAccessible(true);
previousProdMode = prodModeField.get(null);
prodModeField.set(null, false);
disabledField = ComponentTracker.class.getDeclaredField("disabled");
disabledField.setAccessible(true);
previousDisabled = disabledField.get(null);
disabledField.set(null, false);
}

@After
public void teardown() throws Exception {
prodModeField.set(null, previousProdMode);
disabledField.set(null, previousDisabled);
}

@Test
Expand All @@ -71,11 +70,11 @@ public void createLocationTracked() {
c2 = new Component1();

ComponentTracker.Location c1Location = ComponentTracker.findCreate(c1);
Assert.assertEquals(69, c1Location.lineNumber());
Assert.assertEquals(68, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());

ComponentTracker.Location c2Location = ComponentTracker.findCreate(c2);
Assert.assertEquals(71, c2Location.lineNumber());
Assert.assertEquals(70, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());
}

Expand All @@ -88,13 +87,13 @@ public void attachLocationTracked() {
Layout layout = new Layout(c1);

ComponentTracker.Location c1Location = ComponentTracker.findAttach(c1);
Assert.assertEquals(88, c1Location.lineNumber());
Assert.assertEquals(87, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());

layout.add(c2);

ComponentTracker.Location c2Location = ComponentTracker.findAttach(c2);
Assert.assertEquals(94, c2Location.lineNumber());
Assert.assertEquals(93, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());

// Last attach is tracked
Expand All @@ -103,7 +102,7 @@ public void attachLocationTracked() {
layout.add(c3);

ComponentTracker.Location c3Location = ComponentTracker.findAttach(c3);
Assert.assertEquals(103, c3Location.lineNumber());
Assert.assertEquals(102, c3Location.lineNumber());
Assert.assertEquals(getClass().getName(), c3Location.className());
}

Expand All @@ -114,19 +113,19 @@ public void offsetApplied() {
Component c3 = new Component1();

ComponentTracker.Location c1Location = ComponentTracker.findCreate(c1);
Assert.assertEquals(112, c1Location.lineNumber());
Assert.assertEquals(111, c1Location.lineNumber());
Assert.assertEquals(getClass().getName(), c1Location.className());

ComponentTracker.refreshLocation(c1Location, 3);

ComponentTracker.Location c2Location = ComponentTracker.findCreate(c2);
Assert.assertEquals(113 + 3, c2Location.lineNumber());
Assert.assertEquals(112 + 3, c2Location.lineNumber());
Assert.assertEquals(getClass().getName(), c2Location.className());

ComponentTracker.refreshLocation(c2Location, 1);

ComponentTracker.Location c3Location = ComponentTracker.findCreate(c3);
Assert.assertEquals(114 + 3 + 1, c3Location.lineNumber());
Assert.assertEquals(113 + 3 + 1, c3Location.lineNumber());
Assert.assertEquals(getClass().getName(), c3Location.className());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright 2000-2023 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.flow;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.function.Consumer;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;

import com.vaadin.flow.component.internal.ComponentTracker;
import com.vaadin.flow.function.DeploymentConfiguration;
import com.vaadin.flow.internal.CurrentInstance;
import com.vaadin.flow.server.InitParameters;
import com.vaadin.flow.server.MockVaadinServletService;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.startup.ApplicationConfiguration;

public class DisableComponentTrackerTest {
private Object previousDisabled;
private Field disabledField;

@Before
public void setup() throws Exception {
disabledField = ComponentTracker.class.getDeclaredField("disabled");
disabledField.setAccessible(true);
previousDisabled = disabledField.get(null);
disabledField.set(null, null);
}

@After
public void teardown() throws Exception {
disabledField.set(null, previousDisabled);
}

@Test
public void trackCreate_disabledInProductionMode() {
withVaadinEnvironment(appCfg -> {
Mockito.when(appCfg.isProductionMode()).thenReturn(true);
Mockito.when(appCfg.getBooleanProperty(ArgumentMatchers.eq(
InitParameters.APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER),
ArgumentMatchers.anyBoolean())).then(i -> i.getArgument(1));

ComponentTrackerTest.Component1 c1 = new ComponentTrackerTest.Component1();
Assert.assertNull(ComponentTracker.findCreate(c1));
});
}

@Test
public void trackAttach_disabledInProductionMode() {
withVaadinEnvironment(appCfg -> {
Mockito.when(appCfg.isProductionMode()).thenReturn(true);
Mockito.when(appCfg.getBooleanProperty(ArgumentMatchers.eq(
InitParameters.APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER),
ArgumentMatchers.anyBoolean())).then(i -> i.getArgument(1));

ComponentTrackerTest.Component1 c1 = new ComponentTrackerTest.Component1();
ComponentTrackerTest.Layout layout = new ComponentTrackerTest.Layout(
c1);
Assert.assertNull(ComponentTracker.findAttach(c1));
});
}

@Test
public void trackCreate_disabledByConfiguration() {
withVaadinEnvironment(appCfg -> {
Mockito.when(appCfg.isProductionMode()).thenReturn(false);
Mockito.when(appCfg.getBooleanProperty(ArgumentMatchers.eq(
InitParameters.APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER),
ArgumentMatchers.anyBoolean())).thenReturn(false);

ComponentTrackerTest.Component1 c1 = new ComponentTrackerTest.Component1();
Assert.assertNull(ComponentTracker.findCreate(c1));
});
}

@Test
public void trackAttach_disabledByConfiguration() {
withVaadinEnvironment(appCfg -> {
Mockito.when(appCfg.isProductionMode()).thenReturn(false);
Mockito.when(appCfg.getBooleanProperty(ArgumentMatchers.eq(
InitParameters.APPLICATION_PARAMETER_DEVMODE_ENABLE_COMPONENT_TRACKER),
ArgumentMatchers.anyBoolean())).thenReturn(false);

ComponentTrackerTest.Component1 c1 = new ComponentTrackerTest.Component1();
ComponentTrackerTest.Layout layout = new ComponentTrackerTest.Layout(
c1);
Assert.assertNull(ComponentTracker.findAttach(c1));
});
}

private void withVaadinEnvironment(
Consumer<ApplicationConfiguration> action) {
DeploymentConfiguration configuration = Mockito
.mock(DeploymentConfiguration.class);
ApplicationConfiguration applicationConfiguration = Mockito
.mock(ApplicationConfiguration.class);
Map<Class<?>, CurrentInstance> instances = CurrentInstance
.getInstances();
CurrentInstance.clearAll();
VaadinService service = new MockVaadinServletService(configuration);
service.getContext().setAttribute(ApplicationConfiguration.class,
applicationConfiguration);
try {
CurrentInstance.set(VaadinService.class, service);
action.accept(applicationConfiguration);
} finally {
CurrentInstance.restoreInstances(instances);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1956,11 +1956,10 @@ public void cannotMoveComponentsToOtherUI() {
}

private void resetComponentTrackerProductionMode() throws Exception {
Field productionMode = ComponentTracker.class
.getDeclaredField("productionMode");
productionMode.setAccessible(true);
productionMode.set(null, null);
productionMode.setAccessible(false);
Field disabled = ComponentTracker.class.getDeclaredField("disabled");
disabled.setAccessible(true);
disabled.set(null, null);
disabled.setAccessible(false);
}

}
Loading