Skip to content

Commit

Permalink
feat: allow disable component tracker (#18355)
Browse files Browse the repository at this point in the history
Adds a configuration parameter that allows developers to
disable component tracking.

Fixes #18130
  • Loading branch information
mcollovati committed Dec 28, 2023
1 parent df47c83 commit 4a930bb
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,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 @@ -47,7 +48,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 @@ -172,7 +173,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 @@ -205,7 +206,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 @@ -283,17 +284,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 @@ -313,8 +319,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);
}

}

0 comments on commit 4a930bb

Please sign in to comment.