Browse Source

Show a sensible message for missing extensions (#10799)

Also remove ComponentMissingFromDefaultWidgetsetTest since it's
identical to UnknownComponentConnectorTest

Change-Id: I4b4b8f40c8376f4ea26b73d41191a3e7e811df01
tags/8.0.0.alpha9
Artur Signell 7 years ago
parent
commit
cbbd1710fe

+ 3
- 0
client-compiler/src/main/java/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java View File

@@ -58,6 +58,7 @@ import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.metadata.TypeDataStore;
import com.vaadin.client.metadata.TypeDataStore.MethodAttribute;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;
import com.vaadin.server.widgetsetutils.metadata.ClientRpcVisitor;
import com.vaadin.server.widgetsetutils.metadata.ConnectorBundle;
import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor;
@@ -1123,6 +1124,8 @@ public class ConnectorBundleLoaderFactory extends Generator {
connectorsByLoadStyle.get(LoadStyle.EAGER));
eagerBundle.processType(eagerLogger, typeOracle
.findType(UnknownComponentConnector.class.getCanonicalName()));
eagerBundle.processType(eagerLogger, typeOracle
.findType(UnknownExtensionConnector.class.getCanonicalName()));
eagerBundle.processSubTypes(eagerLogger,
typeOracle.getType(ClientRpc.class.getName()));
eagerBundle.processSubTypes(eagerLogger,

+ 4
- 1
client-compiler/src/main/java/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java View File

@@ -48,6 +48,7 @@ import com.vaadin.client.communication.JSONSerializer;
import com.vaadin.client.connectors.AbstractRendererConnector;
import com.vaadin.client.metadata.TypeDataStore.MethodAttribute;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;
import com.vaadin.shared.communication.ClientRpc;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.ui.Connect;
@@ -469,7 +470,9 @@ public class ConnectorBundle {
private static boolean isConnected(JClassType type) {
return type.isAnnotationPresent(Connect.class)
|| type.getQualifiedSourceName().equals(
UnknownComponentConnector.class.getCanonicalName());
UnknownComponentConnector.class.getCanonicalName())
|| type.getQualifiedSourceName().equals(
UnknownExtensionConnector.class.getCanonicalName());
}

public static boolean isConnectedComponentConnector(JClassType type) {

+ 20
- 1
client/src/main/java/com/vaadin/client/ApplicationConfiguration.java View File

@@ -53,6 +53,7 @@ import com.vaadin.client.metadata.ConnectorBundleLoader;
import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.ui.ui.UIConstants;
@@ -526,7 +527,11 @@ public class ApplicationConfiguration implements EntryPoint {
currentTag = getParentTag(currentTag.intValue());
}
if (type == null) {
type = UnknownComponentConnector.class;
if (isExtensionType(tag)) {
type = UnknownExtensionConnector.class;
} else {
type = UnknownComponentConnector.class;
}
if (unknownComponents == null) {
unknownComponents = new HashMap<>();
}
@@ -537,6 +542,20 @@ public class ApplicationConfiguration implements EntryPoint {
return type;
}

private boolean isExtensionType(int tag) {
Integer currentTag = Integer.valueOf(tag);
while (currentTag != null) {
String serverSideClassNameForTag = getServerSideClassNameForTag(
currentTag);
if ("com.vaadin.server.AbstractExtension"
.equals(serverSideClassNameForTag)) {
return true;
}
currentTag = getParentTag(currentTag.intValue());
}
return false;
}

public void addComponentInheritanceInfo(ValueMap valueMap) {
JsArrayString keyArray = valueMap.getKeyArray();
for (int i = 0; i < keyArray.length(); i++) {

+ 3
- 1
client/src/main/java/com/vaadin/client/VUIDLBrowser.java View File

@@ -36,6 +36,7 @@ import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;
import com.vaadin.client.ui.VWindow;

import elemental.json.JsonArray;
@@ -229,7 +230,8 @@ public class VUIDLBrowser extends SimpleTree {
int tag) {
Class<? extends ServerConnector> widgetClassByDecodedTag = conf
.getConnectorClassByEncodedTag(tag);
if (widgetClassByDecodedTag == UnknownComponentConnector.class) {
if (widgetClassByDecodedTag == UnknownComponentConnector.class
|| widgetClassByDecodedTag == UnknownExtensionConnector.class) {
return conf.getUnknownServerClassNameByTag(tag)
+ "(NO CLIENT IMPLEMENTATION FOUND)";
} else {

+ 31
- 19
client/src/main/java/com/vaadin/client/WidgetSet.java View File

@@ -26,6 +26,8 @@ import com.vaadin.client.metadata.ConnectorBundleLoader;
import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;

public class WidgetSet {
/**
@@ -55,33 +57,43 @@ public class WidgetSet {
Class<? extends ServerConnector> classType = resolveInheritedConnectorType(
conf, tag);

if (classType == null || classType == UnknownComponentConnector.class) {
String serverSideName = conf.getUnknownServerClassNameByTag(tag);
UnknownComponentConnector c = GWT
.create(UnknownComponentConnector.class);
c.setServerSideClassName(serverSideName);
Profiler.leave("WidgetSet.createConnector");
return c;
} else {
/*
* let the auto generated code instantiate this type
*/
try {
try {
if (classType == null
|| classType == UnknownComponentConnector.class
|| classType == UnknownExtensionConnector.class) {
String serverSideName = conf
.getUnknownServerClassNameByTag(tag);
if (classType == UnknownExtensionConnector.class) {
// Display message in the console for non-visual connectors
getLogger().severe(UnknownComponentConnector
.createMessage(serverSideName));
return GWT.create(UnknownExtensionConnector.class);
} else {
UnknownComponentConnector c = GWT
.create(UnknownComponentConnector.class);
// Set message to be shown in a widget for visual connectors
c.setServerSideClassName(serverSideName);
return c;
}
} else {
/*
* let the auto generated code instantiate this type
*/
ServerConnector connector = (ServerConnector) TypeData
.getType(classType).createInstance();
if (connector instanceof HasJavaScriptConnectorHelper) {
((HasJavaScriptConnectorHelper) connector)
.getJavascriptConnectorHelper().setTag(tag);
}
Profiler.leave("WidgetSet.createConnector");
return connector;
} catch (NoDataException e) {
Profiler.leave("WidgetSet.createConnector");
throw new IllegalStateException(
"There is no information about " + classType
+ ". Did you remember to compile the right widgetset?",
e);
}
} catch (NoDataException e) {
throw new IllegalStateException(
"There is no information about " + classType
+ ". Did you remember to compile the right widgetset?",
e);
} finally {
Profiler.leave("WidgetSet.createConnector");
}
}


+ 3
- 1
client/src/main/java/com/vaadin/client/debug/internal/OptimizedWidgetsetPanel.java View File

@@ -26,6 +26,7 @@ import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.Util;
import com.vaadin.client.ui.UnknownComponentConnector;
import com.vaadin.client.ui.UnknownExtensionConnector;

/**
* Optimized widgetset view panel of the debug window.
@@ -89,7 +90,8 @@ public class OptimizedWidgetsetPanel extends FlowPanel {
break;
}

if (connectorClass != UnknownComponentConnector.class) {
if (connectorClass != UnknownComponentConnector.class
&& connectorClass != UnknownExtensionConnector.class) {
usedConnectors.add(connectorClass.getName());
}
tag++;

+ 8
- 4
client/src/main/java/com/vaadin/client/ui/UnknownComponentConnector.java View File

@@ -31,13 +31,17 @@ public class UnknownComponentConnector extends AbstractComponentConnector {
}

public void setServerSideClassName(String serverClassName) {
getWidget().setCaption("Widgetset '" + GWT.getModuleName()
+ "' does not contain implementation for " + serverClassName
+ ". Check its component connector's @Connect mapping, widgetsets "
getWidget().setCaption(createMessage(serverClassName));
}

public static String createMessage(String serverClassName) {
return "Widgetset '" + GWT.getModuleName()
+ "' does not contain an implementation for " + serverClassName
+ ". Check the connector's @Connect mapping, the widgetset's "
+ "GWT module description file and re-compile your"
+ " widgetset. In case you have downloaded a vaadin"
+ " add-on package, you might want to refer to "
+ "<a href='http://vaadin.com/using-addons'>add-on "
+ "instructions</a>.");
+ "instructions</a>.";
}
}

+ 33
- 0
client/src/main/java/com/vaadin/client/ui/UnknownExtensionConnector.java View File

@@ -0,0 +1,33 @@
/*
* Copyright 2000-2014 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.client.ui;

import com.vaadin.client.ServerConnector;
import com.vaadin.client.extensions.AbstractExtensionConnector;

/**
* Connector used as a placeholder for extensions that are not present in the
* widgetset.
*
* @since
* @author Vaadin Ltd
*/
public class UnknownExtensionConnector extends AbstractExtensionConnector {
@Override
protected void extend(ServerConnector target) {
// Noop
}
}

+ 45
- 0
uitest/src/main/java/com/vaadin/tests/extensions/UnknownExtensionHandling.java View File

@@ -0,0 +1,45 @@
/*
* Copyright 2000-2014 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.tests.extensions;

import com.vaadin.server.AbstractClientConnector;
import com.vaadin.server.AbstractExtension;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Label;

public class UnknownExtensionHandling extends AbstractTestUI {

// Extension without @Connect counterpart
public static class MyExtension extends AbstractExtension {
@Override
public void extend(AbstractClientConnector target) {
super.extend(target);
}
}

@Override
protected void setup(VaadinRequest request) {
Label label = new Label(
"A label with a missing extension, should cause sensible output in the debug window / browser console");

MyExtension extension = new MyExtension();
extension.extend(label);

addComponent(label);
}

}

+ 39
- 0
uitest/src/test/java/com/vaadin/tests/components/UnknownComponentConnectorTest.java View File

@@ -0,0 +1,39 @@
/*
* Copyright 2000-2014 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.tests.components;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.openqa.selenium.WebElement;

import com.vaadin.tests.tb3.MultiBrowserTest;

/**
* Tests that a user is notified about a missing component from the widgetset
*/
public class UnknownComponentConnectorTest extends MultiBrowserTest {

@Test
public void testConnectorNotFoundInWidgetset() throws Exception {
openTestURL();
WebElement component = vaadinElementById("no-connector-component");
assertTrue(component.getText().startsWith(
"Widgetset 'com.vaadin.DefaultWidgetSet' does not contain an "
+ "implementation for com.vaadin.tests.components.UnknownComponentConnector."
+ "ComponentWithoutConnector."));
}
}

+ 58
- 0
uitest/src/test/java/com/vaadin/tests/extensions/UnknownExtensionHandlingTest.java View File

@@ -0,0 +1,58 @@
/*
* Copyright 2000-2014 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.tests.extensions;

import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import com.vaadin.tests.extensions.UnknownExtensionHandling.MyExtension;
import com.vaadin.tests.tb3.SingleBrowserTest;

public class UnknownExtensionHandlingTest extends SingleBrowserTest {

@Test
public void testUnknownExtensionHandling() {
setDebug(true);
openTestURL();

openDebugLogTab();

Assert.assertTrue(
hasMessageContaining(MyExtension.class.getCanonicalName()));

Assert.assertFalse(hasMessageContaining("Hierachy claims"));
}

private boolean hasMessageContaining(String needle) {
List<WebElement> elements = findElements(
By.className("v-debugwindow-message"));
for (WebElement messageElement : elements) {
// Can't use getText() since element isn't scrolled into view
String text = (String) executeScript(
"return arguments[0].textContent", messageElement);
if (text.contains(needle)) {
return true;
}
}

return false;
}

}

Loading…
Cancel
Save