GWT Compiler : when is a compilation error fatal? - java

I'm trying to understand more about how GWT compilation works.
More specifically, I want to know how does GWT decide that a particular error is fatal, and the app compilation should fail because of it, and how does it decide that compilation is successful, even though there are compilation errors.
The reason I'm asking is that it's very difficult to distinguish legitimate errors in my log when doing a search, from ones that don't seem to cause any problem.
I'm talking about GWT 2.7 and GWT 2.8 (which I've seen they exhibit the same behavior).
Also, I'm using GWTP 1.5.3, if this is relevant somewhat.
A concrete example: I have this error in my logs:
Tracing compile failure path for type 'myApp.ClientModule'
Errors in 'file:/E:/data/.../myApp/ClientModule.java'
Line 24: No source code is available for type myApp.client.ServicesProvidersModuleGen; did you forget to inherit a required module?
Checked 1 dependencies for errors.
The error above does not make my app to fail compilation, and myApp works just fine (the class is something that registers some GIN bindings, which also work).
Why didn't GWT failed my compilation when it encountered that error?
Additionally, I also have other errors such as:
Errors in 'com/google/gwt/validation/client/impl/AbstractGwtSpecificValidator.java'
Line 102: No source code is available for type javax.validation.ValidationException; did you forget to inherit a required module?
Line 177: No source code is available for type javax.validation.ConstraintValidator<A,T>; did you forget to inherit a required module?
Line 153: No source code is available for type javax.validation.groups.Default; did you forget to inherit a required module?
Line 302: No source code is available for type javax.validation.ConstraintViolation<T>; did you forget to inherit a required module?
These errors also don't fail my compilation. Why?
Edit1: forgot to add.
I'm tempted to guess that compilation fails when the error is in something directly reachable from an entry point, and that compilation is OK when that code is not reachable.
However, I have the counter-example of code with annotations.
I have code that IS reachable from the entry point, and has annotations whose source code is not available, and yet the compilation succeeds (although this is the only exception that I could find so far).

Your analysis is good.
GWT will scan the entire classpath, ignoring everything not in the source path and "rebasing" super-sources. During that scan, it emits the kind of error you saw, but only when code will reach the missing sources (from entry points) the error will become fatal. Annotations are no exception, but code will never actually reach them as their just metadata (unless you implement an #interface, which Java allows). Annotations can be used by generators though, in which case they can fail the build.
Note that if you use -failOnError (or -strict, which is an alias), then all errors are fatal. You should aim for turning this on IMO.

Related

How to debug Dagger2 not generating components

Is there a way to get dagger to spit out why it didn't generate a particular component?
I tried refactoring some of our modules and ended up breaking something, but I have literally no idea what I broke! All I see is that all my DaggerFoo components are missing, because dagger is apparently silently failing.
I've tried compiling with verbosity & higher max errors, but I still see absolutely nothing from Dagger itself saying what went wrong.
-Xdiags:verbose
-Xmaxerrs=1000
I have no relevant errors to share, because none are printed!
How the heck do you debug Dagger2?
Dagger runs as an annotation processor, so its error messages will manifest as compiler errors. These will often look like this message ("X cannot be provided...").
error: some.injected.ClassName cannot be provided without an #Inject constructor
or from an #Provides- or #Produces-annotated method.
some.injected.ClassName is injected at
some.class.that.InjectsIt
some.class.that.InjectsThatAbove
some.class.that.FurtherInjectsThat
If you're not sure where to look for compiler errors, you can see some other answers here:
Android Studio: Where is the Compiler Error Output Window?
How to view the list of compile errors in IntelliJ?
eclipse annotation processor not working. Where are errors shown?
If you've edited your project configuration or Gradle definition, it is also possible that Dagger is no longer running at all, or that it hasn't run for a while and has been working only based on its previous output. If so, check your Gradle file or Eclipse project definition to ensure that you are including Dagger as an annotationProcessor, and that you have at least one #Component file for that annotation processor to find.

GWT-Jackson-Apt seemingly undefined class constructor call

Looking at trying to use the GWT-Jackson-Apt library for doing certain RPC, but when looking at examples and trying to run some demos there are always interfaces with a bizarre undefined constructor call.
#JSONMapper
public interface SampleMapper extends ObjectMapper<SimpleBean> {
SampleMapper INSTANCE = new App_SampleMapperImpl();
}
source: https://github.com/DominoKit/gwt-jackson-apt/blob/f60d0358b90bcbf78d066796f680aeae1d7156bb/samples/basic/basic-client/src/main/java/org/dominokit/jacksonapt/samples/basic/App.java
I've been digging around, but there is no definition of App_SampleMapperImpl() anywhere in the source code. And it doesn't compile, saying that there is an undefined symbol
The exact same thing is done in the readme file's exmaples which can be found on this page: https://github.com/DominoKit/gwt-jackson-apt/tree/f60d0358b90bcbf78d066796f680aeae1d7156bb
can anyone explain what is going on here? How is this constructor being defined, or implied? And what do I need to do to make the example compile?
Assuming you are making a Maven project, the important thing is to include the annotation processor which generates the mappers. Then, once the project knows how to generate them, you'll be able to use them in your code.
Annotation Processors run while the compiler is running, which means you technically get to write code which doesn't appear it will compile. Then, as the compiler is running, it asks all registered annotation processors to please generate code based on the annotations and existing types (not the missing references like App_Sample_MapperImpl as you might think). The processor then runs, generates the missing class, and then the compile continues.
Usually what happens is that you build while writing code (eclipse, for example, does this every time a file is saved, intellij does it when you ask for a build, etc), and then the class exists and can be referenced going forward. Even when the project is cleaned and rebuilt, while the reference seems like it should not work, it will work as soon as the compiler runs.
In this case, we'll need to follow the example to make sure the processor is present. in https://github.com/DominoKit/gwt-jackson-apt/blob/f60d0358b90bcbf78d066796f680aeae1d7156bb/samples/shared-mappers/shared-mappers-shared/pom.xml, we see this in the dependencies:
<dependency>
<groupId>org.dominokit.jackson</groupId>
<artifactId>jackson-apt-processor</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
This is marked scope=provided since it is only needed to compile, then shouldn't be included in later dependency graphs. For each specific IDE, you may need to specify additional options to get it to re-run automatically (a checkbox in Eclipse, nothing in IntelliJ I believe, and I haven't used other IDEs in too long to say).
One final note for maven: you must use a relatively recent maven-compiler-plugin so that generated code is handled correctly: latest is 3.8.0, published July 2018, but I think anything after 3.5.1 will be sufficient if you must use an older one.
Just follow the example on the main page of the project: https://github.com/DominoKit/gwt-jackson-apt/
Does that work ?

How to debug project.clj to find which dependency is breaking my project compilation

I have just updated my system from Java 8 to the OpenJDK Java 11 version. I have one project that won't compile and I get the following error:
Java.lang.IllegalArgumentException: Must hint overloaded method:
toArray, compiling:(flatland/ordered/set.clj:19:1)
Exception in thread "main" java.lang.IllegalArgumentException: Must
hint overloaded method: toArray, compiling:
(flatland/ordered/set.clj:19:1)
From the looks of it, this error was fixed here: https://dev.clojure.org/jira/browse/CLJ-2374
So I update my project to clojure 1.10.0-RC3 and now I get this error:
Syntax error compiling deftype* at (flatland/ordered/set.clj:19:1).
Exception in thread "main" Syntax error compiling deftype* at
(flatland/ordered/set.clj:19:1).
Has anyone seen this error OR is there a way for me to expand Clojure's error messages to show me which dependency in my project is failing during compilation (could be multiple)?
I also noticed that I copied over the dependency list which was failing in my first project to a new project and the new project compiled. However, I didn't reference the dependencies or call functions from the deps list. Does Clojure bring in the dependencies/libraries and then reference the required dependencies from the libraries that are included in my project.clj?
EDIT***
I found that this is likely the error.
https://github.com/amalloy/ordered/pull/37
You already have an answer though I thought i'd leave my general process for this incase it's useful for folks who come along later:
turn of any auto AOT in my tooling so i can get a repl witout triggering the problem.
load namespaces one at a time till i find one that triggers the problem (this usually doesn't take long ;-)
comment out half the dependencies of that namespace and evaluate the ns form at the top of the file
do a binary search till i find the one or two that trigger it
load just that dependency in a scrap project.
... lots of effort ...
SUCCESS !

Why does GWT compile errors won't break the maven build?

I'm building a GWT project in maven using gwt-maven-plugin.
Recently I noticed an error on a class, where some server code was called on a client class. At first I thought that something was wrong with the gwt compilation (not including this class). But then I notice that it was compiling that class and it was throwing the error on info log level.
[INFO] Tracing compile failure path for type 'com.mycompany.shared.IElement'
[INFO] Errors in 'jar:file:/Users/myuser/.m2/repository/com/mycompany/package/package-java/1.0.0-SNAPSHOT/package-java-1.0.0-SNAPSHOT-sources.jar!/com/mycompany/shared/IElement.java'
[INFO] Line 45: No source code is available for type com.mycompany.test.Tester; did you forget to inherit a required module?
Why this is only a info log?
Why this does not breaks the build?
Can I force the build to break upon this kind of errors?
Yes you can, and in fact you should! Its even likely that this option will be on by default in the future, as these sorts of 'recoverable' errors cause performance issues in the compiler as it keeps recovering and working around the missing code.
Using the maven plugin, you can simply set this flag to true. From http://mojo.codehaus.org/gwt-maven-plugin/compile-mojo.html#failOnError,
failOnError:
Fail compilation if any input file contains an error.
Can be set from command line using '-Dgwt.compiler.strict=true'.
In your plugin's <configuration> block, this looks like
<failOnError>true</failOnError>
(This used to be called <strict>, and in some of my own pom files, still lives that way...)

Classpath not working

My project requires the gif4j suite. So I set the classpath to "C:...\gif4j_pro_trial_2.3.jar" in the Environmental Variables window from my Control Panel. I know that when we have multiple values for classpath, you seperate them with a semi-colon. I did that too. But I'm still getting this error when I run the file.
Exception in thread "AWT-EventQueue-0" java.lang.Error: Unresolved compilation problems:
The import com.gif4j.TextPainter cannot be resolved
The import com.gif4j.Watermark cannot be resolved
I don't really understand what's going on here since I'm not the one who wrote the code. What am I missing?
This error doesn't say anything about not being able to find the gif4j classes at runtime. Instead, it's saying that, when the code was compiled, those classes weren't available. javac does not produce these kinds of errors (instead it simply fails to compile), so I'm assuming this code was compiled by Eclipse. In that case, you should check your Eclipse project configuration and make sure that the gif4j libraries are properly included there.
The throw new Error(..() statement has been created by eclipse. Whenever eclipse can't compile a class because of compile time errors in methods, it tries to create stubs for those methods. So you'll always find a class file, even if the source code has errors.
Such a method would look like (example):
public long calculate(long a, long b) {
throw new Error("Unresolved compilation problems"); // + additional information
}
It doesn't actually exist in your source, it's only created on byte code level.
So, what has happened: Most likely that you (or someone else) ignored error markers in your project and now tried to use the class files in the bin folder. You can't fix that problem at runtime, you have fix the project to create properly compiled classes.

Categories