From 9e3505ff63925729dbdb2ecdedd392ff28e1db8a Mon Sep 17 00:00:00 2001 From: BenDol Date: Sat, 19 Sep 2015 20:46:02 +1200 Subject: [PATCH 1/2] Stop swallowing compile errors ApplicationControllerGenerator! When a type produces GWT compile errors (i.e. Java compile errors or non-client code errors) the TypeOracle#findType returns null on types that are affected by the compile error. Most of the time this would be the entry point classes, resulting in an ambiguous error message when producing the ApplicationController. For example when it attempts to load the Bootstrapper it returns the type as null when there are Java compile errors or GWT client specific compile errors originating from the entry-point class. For example, this is the error I would expect to see: [WARN] Class com.bugs.NotInClientOrSharedPackage is used in Gin, but not available in GWT client code. But instead I would get something like this: [ERROR] The type 'nz.co.doltech.xxx.client.Application.PreBootstrapImpl' was not found. This issue has bugged be for quite some time now especially when an ammeter with GWT is using GWTP so its nice to finally have it resolved! --- .../ApplicationControllerFallback.java | 48 +++++++++++++++++++ .../client/fallback/BootstrapperFallback.java | 42 ++++++++++++++++ .../fallback/PreBootstrapperFallback.java | 42 ++++++++++++++++ .../ApplicationControllerGenerator.java | 44 +++++++++++++---- pom.xml | 4 ++ 5 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/ApplicationControllerFallback.java create mode 100644 gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/BootstrapperFallback.java create mode 100644 gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/PreBootstrapperFallback.java diff --git a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/ApplicationControllerFallback.java b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/ApplicationControllerFallback.java new file mode 100644 index 0000000000..dbd1d078e7 --- /dev/null +++ b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/ApplicationControllerFallback.java @@ -0,0 +1,48 @@ +/* + * Copyright 2015 ArcBees Inc. + * + * 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.gwtplatform.mvp.client.fallback; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.RootPanel; +import com.gwtplatform.mvp.client.ApplicationController; + +public class ApplicationControllerFallback implements ApplicationController { + + public static final String REASON = "There must have been an issue generating " + + "the ApplicationController. Please check your module configuration, ensure there " + + "are no compile errors in your source code and ensure you are not importing sources " + + "that cannot be compiled by GWT."; + + @Override + public void init() { + GWT.log(REASON); + + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + @Override + public void execute() { + RootPanel.get().add(new HTML("

" + REASON + "

")); + } + }); + } + + @Override + public void onModuleLoad() { + init(); + } +} diff --git a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/BootstrapperFallback.java b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/BootstrapperFallback.java new file mode 100644 index 0000000000..3392daae04 --- /dev/null +++ b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/BootstrapperFallback.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 ArcBees Inc. + * + * 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.gwtplatform.mvp.client.fallback; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.RootPanel; +import com.gwtplatform.mvp.client.Bootstrapper; + +public class BootstrapperFallback implements Bootstrapper { + + private static final String REASON = "There must have been an issue generating the Bootstrapper. " + + "Please check your module configuration, ensure there are no compile errors in your source code " + + "and ensure you are not importing sources that cannot be compiled by GWT."; + + @Override + public void onBootstrap() { + GWT.log(REASON); + + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + @Override + public void execute() { + RootPanel.get().add(new HTML("

" + REASON + "

")); + } + }); + } +} diff --git a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/PreBootstrapperFallback.java b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/PreBootstrapperFallback.java new file mode 100644 index 0000000000..696dfea1bb --- /dev/null +++ b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/client/fallback/PreBootstrapperFallback.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 ArcBees Inc. + * + * 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.gwtplatform.mvp.client.fallback; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.RootPanel; +import com.gwtplatform.mvp.client.PreBootstrapper; + +public class PreBootstrapperFallback implements PreBootstrapper { + + private static final String REASON = "There must have been an issue generating the PreBootstrapper. " + + "Please check your module configuration, ensure there are no compile errors in your source code " + + "and ensure you are not importing sources that cannot be compiled by GWT."; + + @Override + public void onPreBootstrap() { + GWT.log(REASON); + + Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { + @Override + public void execute() { + RootPanel.get().add(new HTML("

" + REASON + "

")); + } + }); + } +} diff --git a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java index 5098eb0ec5..461b706f8e 100644 --- a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java +++ b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java @@ -31,6 +31,9 @@ import com.gwtplatform.mvp.client.Bootstrapper; import com.gwtplatform.mvp.client.DelayedBindRegistry; import com.gwtplatform.mvp.client.PreBootstrapper; +import com.gwtplatform.mvp.client.fallback.ApplicationControllerFallback; +import com.gwtplatform.mvp.client.fallback.BootstrapperFallback; +import com.gwtplatform.mvp.client.fallback.PreBootstrapperFallback; /** * Will generate a {@link com.gwtplatform.mvp.client.ApplicationController}. If the user wants his Generator to be @@ -38,10 +41,13 @@ * revealCurrentPlace() from the place manager. */ public class ApplicationControllerGenerator extends AbstractGenerator { + private static final String PROBLEM_GENERATING = "There was a problem generating the ApplicationController," + + " this can be caused by bad GWT module configuration or compile errors in your source code."; private static final String PROPERTY_BOOTSTRAPPER_EMPTY = "Required configuration property 'gwtp.bootstrapper' can not be empty!."; private static final String PROPERTY_NOT_FOUND = "Undefined configuration property '%s'."; - private static final String TYPE_NOT_FOUND = "The type '%s' was not found."; + private static final String TYPE_NOT_FOUND = "The type '%s' was not found, either the class name is " + + "wrong or there are compile errors in your code."; private static final String HINT_URL = "https://github.com/ArcBees/GWTP/wiki/Bootstrapping"; private static final String DOES_NOT_EXTEND_INTERFACE = "'%s' doesn't implement the '%s' interface. See " + HINT_URL; @@ -73,7 +79,6 @@ public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, return typeName + SUFFIX; } try { - JClassType preBootstrapper = getPreBootstrapper(); ClassSourceFileComposerFactory composer = initComposer(preBootstrapper); @@ -89,6 +94,15 @@ public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, closeDefinition(sw); return getPackageName() + "." + getClassName(); + } catch (UnableToCompleteException e) { + // Java compile errors can cause problems during compilation + // for tasks like TypeOracle#findType will return null if there + // are compile errors, we should at least hint this possibility. + getTreeLogger().log(TreeLogger.ERROR, PROBLEM_GENERATING); + + // Return ApplicationControllerFallback class to avoid + // swallowing the actual compiler issues if there are any. + return ApplicationControllerFallback.class.getName(); } finally { printWriter.close(); } @@ -117,12 +131,11 @@ private ClassSourceFileComposerFactory initComposer(JClassType preBootstrapper) private JClassType getBootstrapper() throws UnableToCompleteException { String typeName = lookupTypeNameByProperty(PROPERTY_NAME_BOOTSTRAPPER); if (typeName == null) { - getTreeLogger() - .log(TreeLogger.ERROR, PROPERTY_BOOTSTRAPPER_EMPTY); - throw new UnableToCompleteException(); + + getTreeLogger().log(TreeLogger.ERROR, PROPERTY_BOOTSTRAPPER_EMPTY); } - return findAndVerifyType(typeName, Bootstrapper.class); + return findAndVerifyType(typeName, Bootstrapper.class, BootstrapperFallback.class); } /** @@ -134,7 +147,8 @@ private JClassType getPreBootstrapper() throws UnableToCompleteException { return null; } - return findAndVerifyType(typeName, PreBootstrapper.class); + return findAndVerifyType(typeName, PreBootstrapper.class, + PreBootstrapperFallback.class); } /** @@ -163,10 +177,22 @@ private String lookupTypeNameByProperty(String propertyName) throws UnableToComp * Find the Java type by the given class name and verify that it extends the given interface. */ private JClassType findAndVerifyType(String typeName, Class interfaceClass) throws UnableToCompleteException { + return findAndVerifyType(typeName, interfaceClass, null); + } + + /** + * Find the Java type by the given class name and verify that it extends the given interface. + */ + private JClassType findAndVerifyType(String typeName, Class interfaceClass, Class fallbackClass) + throws UnableToCompleteException { JClassType type = getTypeOracle().findType(typeName); if (type == null) { - getTreeLogger().log(TreeLogger.ERROR, String.format(TYPE_NOT_FOUND, typeName)); - throw new UnableToCompleteException(); + if (fallbackClass == null) { + getTreeLogger().log(TreeLogger.ERROR, String.format(TYPE_NOT_FOUND, typeName)); + throw new UnableToCompleteException(); + } else { + type = getTypeOracle().findType(fallbackClass.getName()); + } } JClassType interfaceType = getType(interfaceClass.getName()); diff --git a/pom.xml b/pom.xml index 7300b37d1a..908ef497b2 100644 --- a/pom.xml +++ b/pom.xml @@ -179,6 +179,10 @@ Richard Wallis rdwallis@gmail.com + + Ben Dol + dolb90@gmail.com + From d30fa45bd139743f09ae44bfb87f1dd4c5117f7a Mon Sep 17 00:00:00 2001 From: BenDol Date: Sun, 20 Sep 2015 01:13:24 +1200 Subject: [PATCH 2/2] We should control the fallbacks via try/catch. --- .../ApplicationControllerGenerator.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java index 461b706f8e..e0e77e80e3 100644 --- a/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java +++ b/gwtp-core/gwtp-mvp-client/src/main/java/com/gwtplatform/mvp/rebind/ApplicationControllerGenerator.java @@ -135,7 +135,13 @@ private JClassType getBootstrapper() throws UnableToCompleteException { getTreeLogger().log(TreeLogger.ERROR, PROPERTY_BOOTSTRAPPER_EMPTY); } - return findAndVerifyType(typeName, Bootstrapper.class, BootstrapperFallback.class); + JClassType type; + try { + type = findAndVerifyType(typeName, Bootstrapper.class); + } catch (UnableToCompleteException ex) { + type = findAndVerifyType(typeName, BootstrapperFallback.class); + } + return type; } /** @@ -147,8 +153,13 @@ private JClassType getPreBootstrapper() throws UnableToCompleteException { return null; } - return findAndVerifyType(typeName, PreBootstrapper.class, - PreBootstrapperFallback.class); + JClassType type; + try { + type = findAndVerifyType(typeName, PreBootstrapper.class); + } catch (UnableToCompleteException ex) { + type = findAndVerifyType(typeName, PreBootstrapperFallback.class); + } + return type; } /** @@ -176,23 +187,12 @@ private String lookupTypeNameByProperty(String propertyName) throws UnableToComp /** * Find the Java type by the given class name and verify that it extends the given interface. */ - private JClassType findAndVerifyType(String typeName, Class interfaceClass) throws UnableToCompleteException { - return findAndVerifyType(typeName, interfaceClass, null); - } - - /** - * Find the Java type by the given class name and verify that it extends the given interface. - */ - private JClassType findAndVerifyType(String typeName, Class interfaceClass, Class fallbackClass) + private JClassType findAndVerifyType(String typeName, Class interfaceClass) throws UnableToCompleteException { JClassType type = getTypeOracle().findType(typeName); if (type == null) { - if (fallbackClass == null) { - getTreeLogger().log(TreeLogger.ERROR, String.format(TYPE_NOT_FOUND, typeName)); - throw new UnableToCompleteException(); - } else { - type = getTypeOracle().findType(fallbackClass.getName()); - } + getTreeLogger().log(TreeLogger.ERROR, String.format(TYPE_NOT_FOUND, typeName)); + throw new UnableToCompleteException(); } JClassType interfaceType = getType(interfaceClass.getName());