Why can't JavascriptObject's runtime null pointer be detected? - gwt

After some debugging,I found "com.google.gwt.event.shared.UmbrellaException:One or
more exceptions caught, see full set in UmbrellaException#getCauses' when calling method: [nsIDOMEventListener::handleEvent]"(in web model) is caused by runtime null pointer.Question is why this kind of runtime null pointer exception didn't got thrown out under host model.Actually,blow code won't thrown out any exception and even got alert popup in my laptop(gwt 2.4+java 7 64bit+ubuntu 12.04 64bit+eclipse 3.7).Anybody knows how to enforce eclipse throw out exception whenever a runtime null on JavascriptObject pointer occurs.
public class GWTTest implements EntryPoint
{
public static class JsObj extends JavaScriptObject
{
protected JsObj()
{
}
public final native void setValue(String Value)/*-{
this.Value=Value;
alert(Value);
}-*/;
}
public void onModuleLoad()
{
JsObj jsObj = null;
jsObj.setValue("val");
}
}

The compiler performs a number of optimizations to transform GWT/Java into Javascript.
Types and methods are made final - this allows later steps to understand which methods need to be dispatched as normal, and which can be made static, just calling a single implementation.
Methods are made static, where possible, which allows methods to be inlined
Where possible and reasonable, methods are inlined
That said... When I compile your sample, the body of onModuleLoad() is optimized out to this:
null.nullMethod();
This is the GWT compiler's way of saying 'this will never work' - it notices that the value is always null, and so the method can't be invoked on it. But in Dev Mode, apparently the null object is left pointing at the window object in JavaScript. This is filed at http://code.google.com/p/google-web-toolkit/issues/detail?id=6625 in the GWT project.
If you need to make sure you don't act on a null, test for null before calling the method - it'll get optimized out if, in a test like yours, the value is always null. Runtime exceptions shouldn't be used for controlling code anyway, so you should never rely on a NullPointerException to do anything in your code.

Related

eclipse null analysis field initialization

Using the Null Analysis of Eclipse:
It it possible to define other methods as initializing methods than Constructors?
I have a class like this:
public class Foo {
#NonNull
private Object fooObject;
public Foo() {
super();
}
public void onCreate() {
fooObject = //Something which is not available in the Constructor;
}
Here i get the warning that the NonNull field may has not been initialized. Is there any possibility to kind of declare the init-method as an initalizing one?
I could use #SuppressWarnings("null") for the constructor. But then I ignore all fields, which may instanciated somewhere.
Second chance i see is to make fooObject as #Nullable - but then i need check for null each time i use fooObject.
So is there any better solution?
Null-checking object initialization beyond the constructor is inherently difficult. Several sophisticated approaches exist, all of which require additional annotations.
In your example it seems to be near-impossible, to prove to the compiler, that onCreate() is always called before accessing the field.
A weaker solution has been proposed: #LazyNonNull, an annotation to be used on fields that are initially null, but once initialized can never go back to null. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=414237
Obviously, a static factory method, that gathers all necessary values before invoking a constructor (with arguments) would be a lot easier to get right.

JPA EclipseLink Weaver generates call to porperty getter inside its setter -> NullPointerException

I have an #Embeddable class that uses property access to wrap another object that's not directly mappable by JPA via field access. It looks like this:
#Embeddable
#Access(AccessType.PROPERTY)
public class MyWrapper {
#NotNull
#Transient
private WrappedType wrappedField;
protected MyWrapper() {
}
public MyWrapper(WrappedType wrappedField) {
this.wrappedField = wrappedField;
}
#Transient
public WrappedType getWrappedField() {
return wrappedField;
}
public void setWrappedField(WrappedType wrappedField) {
this.wrappedField = wrappedField;
}
#Column(name = "wrappedTypeColumn")
protected String getJPARepresentation() {
return wrappedField.toString();
}
protected void setJPARepresentation(String jpaRepresentation) {
wrappedField = new WrappedType(jpaRepresentation);
}
}
Persisting an #Entity with a MyWrapper field works fine. But when I execute a query to load the Entity from the database, I get a NullPointerException. The stacktrace and some debugging shows that Eclipselink creates a new instance of MyWrapper by calling its default constructor and then calls the setJPARepresentation() method (as expected).
But now the unexpected happens: the stacktrace shows that the getJPARepresentation() is called from inside the setter, which then of course leads to a NullPointerException when return wrappedField.toString() is executed.
java.lang.NullPointerException
at MyWrapper.getJPARepresentation(MyWrapper.java:27)
at MyWrapper.setJPARepresentation(MyWrapper.java)
... 109 more
Fact is, there is obviously no call to the getter in the code and the stacktrace shows no line number indicating from where in the setter called the getter. So my conclusion would be, that the bytecode weaver of Eclipselink generated the call to the getter.
It's easy to build a workaround, but my question is: Why does Eclipselink do that?
P.S: I'm using EclipseLink 2.3.2.v20111125-r10461 in a GlassFish Server Open Source Edition 3.1.2 (build 23)
When weaving is enabled (default on Glassfish), EclipseLink will weave code into property get/set methods for,
change tracking
fetch groups (partial objects)
lazy (relationships)
For change tracking support the set method will be weaved to check if the new value is different than the old value, so it must call the get method to get the old value.
Now this is still odd, as since your are building a new object, I would not expect the change listener to be set yet, so would expect the change tracking check to be bypassed. You could decompile the code to see exactly what was generated.
The easiest fix is to just put in a null check in your get method, which is probably best in general for your code. You could also switch to field access, which will not have issues with side-affects in get/set methods. You could also use a Converter to handle the conversion, instead of doing the conversion in get/set methods.

GWT - Calling instance method from external javascript

There is this $entry method that we can use in GWT to allow external javascript to execute java methods.
You can see the explanations in their documentation https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI?hl=fr#calling
However, the example there is only with static methods. I'm trying to write it for a non-static method and when I try to call it, I get an exception :
java.lang.ClassCastException: Cannot cast com.google.gwt.core.client.JavaScriptObject$ to mypackage.MyModule
Here is my code :
public native void setRefreshModuleCallback() /*-{
$wnd.refreshModule = $entry(function() {
this.#mypackage.MyModule::refreshModuleJava();
alert('test');
});
}-*/;
public void refreshModuleJava() {
logger.log(Level.WARNING, "REFRESH");
}
What I find very funny is that alert is called, I see the result in the browser, but the call just before is not performed.
Do you know if it's actually possible to do such thing ?
$entry is not about calling java, it's about ensuring a few things go well in GWT: exceptions are routed to the GWT.UncaughtExceptionHandler, and commands scheduled via Scheduler#scheduleEntry and Scheduler#scheduleFinally are correctly called.
Your problem is the this. When the function is called, this is not your MyModule class (it's most probably the $wnd object). This is why the question you linked to uses var that = this. It's about scoping.
You also need to actually call the method, not only reference it: in JSNI, the first pair of parens are for the formal parameters (to disambiguate overloads), and you need another pair passing the actual arguments: that.#mypackage.MyModule::refreshModuleJava()().

FindBugs doesn't find a bug

I would like to use FindBugs to create a report about an application.
I run it and it doesn't find a potential bug like this:
public List<String> getListTrace(A object) {
String arg = object.getArg();
...
}
If object is null, my application will be down.
Why FindBugs doesn't raise an alert?
Findbugs doesn't know if object is allowed to be null or not. You can tell it by using annotations:
import javax.annotation.Nullable;
...
public List<String> getListTrace(#Nullable A object) {
This tells Findbugs (and people reading the code) that it is okay to pass null as the argument to getListTrace. So Findbugs will warn you if you dereference object without checking for null.
That code doesn't look like it has a bug.
If you changed the code to check if object was null, what would you do? The most reasonable action would probably to throw a NullPointerException, right?
That's exactly what your code snippet does; it just lets java do the test automatically when accessing a method.
That this function doesn't check for a null pointer is not a bug. The bug would be if someone passed a null pointer into your function and wasn't prepared for it raising a NullPointerException.
Findbug cannot detect potential null pointer accesses. But Eclipse can give you a warning for potential null pointer access, if you activate the corresponding compiler warning in the preferences.
Raising bug report in such case would result in really big noise. You would get thousands of irrelevant bug messages in the perfectly correct code. Actually FindBugs does smarter thing. If it discovers that the method dereferences the argument without a null-check, it marks internally this method argument as #Nonnull. If you have an explicit annotation (like in TimK answer) which contradicts with this, you will get a warning. Otherwise FindBugs assumes that nobody uses this method with possibly-null argument. And when somebody actually does this, you will get a corresponding warning on the call site. Here's an example:
import java.util.Collections;
import java.util.List;
public class FBNull {
static class A {
String getArg() {
return "str";
}
}
public static List<String> getListTrace(A object) {
String arg = object.getArg();
return Collections.singletonList(arg);
}
public void callSite(A a) {
if (a == null) {
System.out.println("a is null");
}
System.out.println(getListTrace(a)); // NP_NULL_PARAM_DEREF
}
}
From the FindBugs poit of view getListTrace() method is ok. However the callSite method has a bug. It checks its argument for null explicitly, thus it can be null due to application logic. However, it's later passed to getListTrace() which immediately dereferences the argument. Thus you have a bug warning inside the getListTrace() method saying:
Bug: Null passed for non-null parameter of getListTrace(FBNull$A) in FBNull.callSite(FBNull$A)
This method call passes a null value for a non-null method parameter. Either the parameter is annotated as a parameter that should always be non-null, or analysis has shown that it will always be dereferenced.
So if you actually can pass nulls, it can be detected on the call sites.

Failure at loading GWT library

I am trying to deploy a bigger GWT project to start working on it. After several problems I finally ran into the following, which I am not able to solve:
Here is a random piece of code:
service.getSuggestionOracle(this.suggestionString.getText(), new AsyncCallback<List<Entity>>() {
#Override
public void onSuccess(List<Entity> result) {
suggestionString.setStyleName("searchInput");
processSuggestionOracle(result);
}
#Override
public void onFailure(Throwable caught) {
suggestionString.setStyleName("searchInput");
GWT.log("Suggestion fails.");
}
});
Eclipse complains about the two functions onSuccess and onFailure that:
The method onSuccess(List<Entity>) of type new AsyncCallback<List<Entity>>(){} must override a superclass method
Indeed when I hover over the: new AsyncCallback<List<Entity>>() statement, it tells me that If an RPC is successful, then onSuccess(Object) is called, otherwise onFailure(Throwable) is called.
I conclude that there IS a superclasses with declarations for onSuccess and onFailure, but the compiler doesn't find it.
I use GWT-2.4.0 and the GWT library is added to the classpath.
The code above is just a random example, there are about 150 similar errors all over the
project. Additionally, there are several imports like com.xind.gwt.dom.client.DOM,
that can not be resolved.
Does anybody have an idea what I am missing here?
There are two possibilities that I could think of:
you haven't extended RemoteServiceServlet on the server implementation.
or
In this code,
public void onSuccess(List result) {
}
you have List as the returned object. Is this a list of objects of a user-defined class or java datatype? If the list is a user-defined type, then you must serialize the corresponding class by implementing java.io.serializable;