Migration wicket 8.* from 7.*, problem with onRequestHandlerResolved() method on AbstractRequestCycleListener - wicket

I'm working on Wicket 8.* migration when I struggle on onRequestHandlerResolved() under IRequestCycleListener method conversion.
As per my structure of logic in my code wicket 7.15.0
public class MyRequestCycleListener extends AbstractRequestCycleListener{
//All methods override here
#Override
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
if (handler instanceof ListenerInterfaceRequestHandler) {
ListenerInterfaceRequestHandler requestHandler = (ListenerInterfaceRequestHandler) handler;
if (requestHandler.getListenerInterface().getListenerInterfaceClass().isAssignableFrom( IFormSubmitListener.class)) {
//here made some login as well as every onSubmit
}
}
}
}
As wicket 8.* changes
AbstractRequestCycleListener class converts to IRequestCycleListener interface
ListenerInterfaceRequestHandler renamed to ListenerRequestHandler
Deprecates RequestListenerInterface and also IFormSubmitListener makes error
How to convert code to migration on wicket 8.9.0 ?

It should be something like this:
public class MyRequestCycleListener implements IRequestCycleListener{
#Override
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
if (handler instanceof ListenerRequestHandler) {
ListenerRequestHandler requestHandler = (ListenerRequestHandler) handler;
if (requestHandler.getComponent() instanceof Form) {
//here made some login as well as every onSubmit
Form form = (Form) requestHandler.getComponent();
}
}
}
}

Related

How to add custom css class for all components where the 'required' property is true in wicket?

I'm using the jQuery validator plugin in my wicket application (wicket's version is 8.10). It uses CSS classes for identifying the validator that should be applied to the field. To mark the component as required I use the FormComponent#setRequired method. Also, I have my own components (inherited from wicket ones) in which I override the onComponentTag method like that:
#Override
protected void onComponentTag(ComponentTag tag) {
if (isRequired()) {
tag.append("class", CSS.required(), " ");
}
super.onComponentTag(tag);
}
also I use following construction for native wicket components:
if (field.isRequired()) {
field.add(new AttributeAppender("class", CSS.required()));
}
Is there any way to set this behavior for any FormComponent without overriding onCommponentTag or adding an AttributeAppender for each field object? Any global AttributeModifier or something like that?
Yes, there is:
Application.get().getOnComponentTagListeners()
.add(new IOnComponentTagListener() {
#Override
public void onComponentTag(final Component component, final ComponentTag tag) {
if (component instanceOf FormComponent) {
if (((FormComponent) component).isRequired()) {
tag.append("class", CSS.required(), " ");
}
}
}
});

Pushing data from one user to another in Vaadin web app

I get the fact that it might take more than 10 lines of code (hopefully not more than 50), but I was wondering if you could help me anyway.
I'm trying to update one user's UI thread at runtime, based on another user's input. I've created a basic project which implements three predefined users (jim, tom and threeskin). I'd like to send a message from jim to tom and have it appear as a new Label object in tom's UI, without threeskin ever knowing about it, even though they're all logged in. Oh, and jim shouldn't have to refresh his page. The label should just spawn on screen out of it's own accord.
To say that I'd appreciate some help would be the understatement of the decade.
public class User {
public String nume;
public User(String nume) {
super();
this.nume = nume;
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class Engine implements ServletContextListener {
public static ArrayList<User>userbase;
public void contextDestroyed(ServletContextEvent arg0) { }
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("This code is running at startup");
userbase =new ArrayList<User>();
userbase.add(new User("jim"));userbase.add(new User("tom"));userbase.add(new User("threeskin"));
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class InfigeUI extends UI {
User us3r;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = InfigeUI.class)
public static class Servlet extends VaadinServlet {}
protected void init(VaadinRequest request) {
VerticalLayout everything=new VerticalLayout();
setContent(everything);
if (us3r==null){everything.addComponent(auth());}else{everything.addComponent(main());}
}
ComponentContainer auth(){
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
TextField userField=new TextField();
Button login = new Button("Log in");
login.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
us3r=login(userField.getValue());
if (us3r!=null){
saveValue(InfigeUI.this, us3r);
layout.removeAllComponents();
layout.addComponent(main());
}else{Notification.show("I only know jim, tom and threeskin. Which one are you?");}}
});
layout.addComponent(userField);
layout.addComponent(login);
return layout;
}
User login(String nume){
for (int i=0;i<Engine.userbase.size();i++){
if (nume.equals(Engine.userbase.get(i).nume)){return Engine.userbase.get(i);}
}
return null;
}
static void saveValue(InfigeUI ui,User value){
ui.us3r=value;
ui.getSession().setAttribute("something", value);
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("something", value);
}
ComponentContainer main(){
VerticalLayout vl=new VerticalLayout();
Label label=new Label("This is the post-login screen");
String name=new String(us3r.nume);
Label eticheta=new Label(name);
TextField to=new TextField("Send to");
TextField message=new TextField("Message");
Button sendNow=new Button("Send now!");
vl.addComponent(eticheta);
vl.addComponent(label);
vl.addComponent(eticheta);
vl.addComponent(to);
vl.addComponent(message);
vl.addComponent(sendNow);
return vl ;
}
}
Basically you want three things
UI updates for a user which does no action himself, or in other words a message sent from the server to the browser. To enable this, you need to annotate the UI class using #Push. Otherwise, the update will only be shown when the user does something which causes a server visit, e.g. clicks a button
Some way of sending messages between UI instances (there is one UI instance per user). You can use some message bus implementation for this (CDI, Spring, ...) or you can make a simple on using a static field (static fields are shared between all users). See e.g. https://github.com/Artur-/SimpleChat for one way of doing it. It's also a good idea here to avoid all *.getCurrent methods as they in many cases will refer to another UI than you think (e.g. sender when you are in the receiver code), and you will do something else than you intend.
Safely update a UI when a message arrives. This is done using UI.access, also visible in the chat example.
First of all you need to enable the server push on your project help
based on Vaadin Documentation.
However, below code example will give what you want:
Create an Broadcast Listener Interface:
public interface BroadcastListener {
public void receiveBroadcast(final String message);
}
The Broadcaster Class:
public class Broadcaster {
private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>();
public static void register(BroadcastListener listener) {
listeners.add(listener);
}
public static void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static void broadcast(final String message) {
for (BroadcastListener listener : listeners) {
listener.receiveBroadcast(message);
}
}
}
Your UI with Push Enalbed (via Annotation):
#Push
public class BroadcasterUI extends UI implements BroadcastListener {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
final TextArea message = new TextArea("",
"The system is going down for maintenance in 10 minutes");
layout.addComponent(message);
final Button button = new Button("Broadcast");
layout.addComponent(button);
button.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Broadcaster.broadcast(message.getValue());
}
});
// Register broadcast listener
Broadcaster.register(this);
}
#Override
public void detach() {
Broadcaster.unregister(this);
super.detach();
}
#Override
public void receiveBroadcast(final String message) {
access(new Runnable() {
#Override
public void run() {
Notification n = new Notification("Message received",
message, Type.TRAY_NOTIFICATION);
n.show(getPage());
}
});
}
you can find the full link here.

javafx.fxml.LoadException: Controller method "MyFunction" not found

As described below, I Have an EventHandler linked to TextField (text variable), and I want to call a function from this handler that exists in the same class (MyFunction), so I'm getting the error (title of this post) :
Code :
class Example implements Initializable{
//...
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
//...
text.setOnKeyPressed(new EventHandler<KeyEvent>(){
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.ENTER){
MyFunction(text.getText());
}
}
});
//...
}//function initialize ends here
public void MyFuction(String text){
//...
}
//...
}//Class ends here
I'm using javaFX 2.2, I hope my request is quite clear.
The problem seems to be in your FXML file. You are probably doing something like this: <Button text="Button" onAction="#MyFuction"/>while onAction handlers should accept single argument of a type that extends javafx.event.Event
Try to put #FXML in front of your MyFuction() method.

Using GWT Editors with a complex usecase

I'm trying to create a page which is very similar to the Google Form creation page.
This is how I am attempting to model it using the GWT MVP framework (Places and Activities), and Editors.
CreateFormActivity (Activity and presenter)
CreateFormView (interface for view, with nested Presenter interface)
CreateFormViewImpl (implements CreateFormView and Editor< FormProxy >
CreateFormViewImpl has the following sub-editors:
TextBox title
TextBox description
QuestionListEditor questionList
QuestionListEditor implements IsEditor< ListEditor< QuestionProxy, QuestionEditor>>
QuestionEditor implements Editor < QuestionProxy>
QuestionEditor has the following sub-editors:
TextBox questionTitle
TextBox helpText
ValueListBox questionType
An optional subeditor for each question type below.
An editor for each question type:
TextQuestionEditor
ParagraphTextQuestionEditor
MultipleChoiceQuestionEditor
CheckboxesQuestionEditor
ListQuestionEditor
ScaleQuestionEditor
GridQuestionEditor
Specific Questions:
What is the correct way to add / remove questions from the form. (see follow up question)
How should I go about creating the Editor for each question type? I attempted to listen to the questionType value changes, I'm not sure what to do after. (answered by BobV)
Should each question-type-specific editor be wrapper with an optionalFieldEditor? Since only one of can be used at a time. (answered by BobV)
How to best manage creating/removing objects deep in the object hierarchy. Ex) Specifying answers for a question number 3 which is of type multiple choice question. (see follow up question)
Can OptionalFieldEditor editor be used to wrap a ListEditor? (answered by BobV)
Implementation based on Answer
The Question Editor
public class QuestionDataEditor extends Composite implements
CompositeEditor<QuestionDataProxy, QuestionDataProxy, Editor<QuestionDataProxy>>,
LeafValueEditor<QuestionDataProxy>, HasRequestContext<QuestionDataProxy> {
interface Binder extends UiBinder<Widget, QuestionDataEditor> {}
private CompositeEditor.EditorChain<QuestionDataProxy, Editor<QuestionDataProxy>> chain;
private QuestionBaseDataEditor subEditor = null;
private QuestionDataProxy currentValue = null;
#UiField
SimplePanel container;
#UiField(provided = true)
#Path("dataType")
ValueListBox<QuestionType> dataType = new ValueListBox<QuestionType>(new Renderer<QuestionType>() {
#Override
public String render(final QuestionType object) {
return object == null ? "" : object.toString();
}
#Override
public void render(final QuestionType object, final Appendable appendable) throws IOException {
if (object != null) {
appendable.append(object.toString());
}
}
});
private RequestContext ctx;
public QuestionDataEditor() {
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
dataType.setValue(QuestionType.BooleanQuestionType, true);
dataType.setAcceptableValues(Arrays.asList(QuestionType.values()));
/*
* The type drop-down UI element is an implementation detail of the
* CompositeEditor. When a question type is selected, the editor will
* call EditorChain.attach() with an instance of a QuestionData subtype
* and the type-specific sub-Editor.
*/
dataType.addValueChangeHandler(new ValueChangeHandler<QuestionType>() {
#Override
public void onValueChange(final ValueChangeEvent<QuestionType> event) {
QuestionDataProxy value;
switch (event.getValue()) {
case MultiChoiceQuestionData:
value = ctx.create(QuestionMultiChoiceDataProxy.class);
setValue(value);
break;
case BooleanQuestionData:
default:
final QuestionNumberDataProxy value2 = ctx.create(BooleanQuestionDataProxy.class);
value2.setPrompt("this value doesn't show up");
setValue(value2);
break;
}
}
});
}
/*
* The only thing that calls createEditorForTraversal() is the PathCollector
* which is used by RequestFactoryEditorDriver.getPaths().
*
* My recommendation is to always return a trivial instance of your question
* type editor and know that you may have to amend the value returned by
* getPaths()
*/
#Override
public Editor<QuestionDataProxy> createEditorForTraversal() {
return new QuestionNumberDataEditor();
}
#Override
public void flush() {
//XXX this doesn't work, no data is returned
currentValue = chain.getValue(subEditor);
}
/**
* Returns an empty string because there is only ever one sub-editor used.
*/
#Override
public String getPathElement(final Editor<QuestionDataProxy> subEditor) {
return "";
}
#Override
public QuestionDataProxy getValue() {
return currentValue;
}
#Override
public void onPropertyChange(final String... paths) {
}
#Override
public void setDelegate(final EditorDelegate<QuestionDataProxy> delegate) {
}
#Override
public void setEditorChain(final EditorChain<QuestionDataProxy, Editor<QuestionDataProxy>> chain) {
this.chain = chain;
}
#Override
public void setRequestContext(final RequestContext ctx) {
this.ctx = ctx;
}
/*
* The implementation of CompositeEditor.setValue() just creates the
* type-specific sub-Editor and calls EditorChain.attach().
*/
#Override
public void setValue(final QuestionDataProxy value) {
// if (currentValue != null && value == null) {
chain.detach(subEditor);
// }
QuestionType type = null;
if (value instanceof QuestionMultiChoiceDataProxy) {
if (((QuestionMultiChoiceDataProxy) value).getCustomList() == null) {
((QuestionMultiChoiceDataProxy) value).setCustomList(new ArrayList<CustomListItemProxy>());
}
type = QuestionType.CustomList;
subEditor = new QuestionMultipleChoiceDataEditor();
} else {
type = QuestionType.BooleanQuestionType;
subEditor = new BooleanQuestionDataEditor();
}
subEditor.setRequestContext(ctx);
currentValue = value;
container.clear();
if (value != null) {
dataType.setValue(type, false);
container.add(subEditor);
chain.attach(value, subEditor);
}
}
}
Question Base Data Editor
public interface QuestionBaseDataEditor extends HasRequestContext<QuestionDataProxy>, IsWidget {
}
Example Subtype
public class BooleanQuestionDataEditor extends Composite implements QuestionBaseDataEditor {
interface Binder extends UiBinder<Widget, BooleanQuestionDataEditor> {}
#Path("prompt")
#UiField
TextBox prompt = new TextBox();
public QuestionNumberDataEditor() {
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
}
#Override
public void setRequestContext(final RequestContext ctx) {
}
}
The only issue left is that QuestionData subtype specific data isn't being displayed, or flushed. I think it has to do with the Editor setup I'm using.
For example, The value for prompt in the BooleanQuestionDataEditor is neither set nor flushed, and is null in the rpc payload.
My guess is: Since the QuestionDataEditor implements LeafValueEditor, the driver will not visit the subeditor, even though it has been attached.
Big thanks to anyone who can help!!!
Fundamentally, you want a CompositeEditor to handle cases where objects are dynamically added or removed from the Editor hierarchy. The ListEditor and OptionalFieldEditor adaptors implement CompositeEditor.
If the information required for the different types of questions is fundamentally orthogonal, then multiple OptionalFieldEditor could be used with different fields, one for each question type. This will work when you have only a few question types, but won't really scale well in the future.
A different approach, that will scale better would be to use a custom implementation of a CompositeEditor + LeafValueEditor that handles a polymorphic QuestionData type hierarchy. The type drop-down UI element would become an implementation detail of the CompositeEditor. When a question type is selected, the editor will call EditorChain.attach() with an instance of a QuestionData subtype and the type-specific sub-Editor. The newly-created QuestionData instance should be retained to implement LeafValueEditor.getValue(). The implementation of CompositeEditor.setValue() just creates the type-specific sub-Editor and calls EditorChain.attach().
FWIW, OptionalFieldEditor can be used with ListEditor or any other editor type.
We implemented similar approach (see accepted answer) and it works for us like this.
Since driver is initially unaware of simple editor paths that might be used by sub-editors, every sub-editor has own driver:
public interface CreatesEditorDriver<T> {
RequestFactoryEditorDriver<T, ? extends Editor<T>> createDriver();
}
public interface RequestFactoryEditor<T> extends CreatesEditorDriver<T>, Editor<T> {
}
Then we use the following editor adapter that would allow any sub-editor that implements RequestFactoryEditor to be used. This is our workaround to support polimorphism in editors:
public static class DynamicEditor<T>
implements LeafValueEditor<T>, CompositeEditor<T, T, RequestFactoryEditor<T>>, HasRequestContext<T> {
private RequestFactoryEditorDriver<T, ? extends Editor<T>> subdriver;
private RequestFactoryEditor<T> subeditor;
private T value;
private EditorDelegate<T> delegate;
private RequestContext ctx;
public static <T> DynamicEditor<T> of(RequestFactoryEditor<T> subeditor) {
return new DynamicEditor<T>(subeditor);
}
protected DynamicEditor(RequestFactoryEditor<T> subeditor) {
this.subeditor = subeditor;
}
#Override
public void setValue(T value) {
this.value = value;
subdriver = null;
if (null != value) {
RequestFactoryEditorDriver<T, ? extends Editor<T>> newSubdriver = subeditor.createDriver();
if (null != ctx) {
newSubdriver.edit(value, ctx);
} else {
newSubdriver.display(value);
}
subdriver = newSubdriver;
}
}
#Override
public T getValue() {
return value;
}
#Override
public void flush() {
if (null != subdriver) {
subdriver.flush();
}
}
#Override
public void onPropertyChange(String... paths) {
}
#Override
public void setDelegate(EditorDelegate<T> delegate) {
this.delegate = delegate;
}
#Override
public RequestFactoryEditor<T> createEditorForTraversal() {
return subeditor;
}
#Override
public String getPathElement(RequestFactoryEditor<T> subEditor) {
return delegate.getPath();
}
#Override
public void setEditorChain(EditorChain<T, RequestFactoryEditor<T>> chain) {
}
#Override
public void setRequestContext(RequestContext ctx) {
this.ctx = ctx;
}
}
Our example sub-editor:
public static class VirtualProductEditor implements RequestFactoryEditor<ProductProxy> {
interface Driver extends RequestFactoryEditorDriver<ProductProxy, VirtualProductEditor> {}
private static final Driver driver = GWT.create(Driver.class);
public Driver createDriver() {
driver.initialize(this);
return driver;
}
...
}
Our usage example:
#Path("")
DynamicEditor<ProductProxy> productDetailsEditor;
...
public void setProductType(ProductType type){
if (ProductType.VIRTUAL==type){
productDetailsEditor = DynamicEditor.of(new VirtualProductEditor());
} else if (ProductType.PHYSICAL==type){
productDetailsEditor = DynamicEditor.of(new PhysicalProductEditor());
}
}
Would be great to hear your comments.
Regarding your question why subtype specific data isn't displayed or flushed:
My scenario is a little bit different but I made the following observation:
GWT editor databinding does not work as one would expect with abstract editors in the editor hierarchy. The subEditor declared in your QuestionDataEditor is of type QuestionBaseDataEditor and this is fully abstract type (an interface). When looking for fields/sub editors to populate with data/flush GWT takes all the fields declared in this type. Since QuestionBaseDataEditor has no sub editors declared nothing is displayed/flushed. From debugging I found out that is happens due to GWT using a generated EditorDelegate for that abstract type rather than the EditorDelegate for the concrete subtype present at that moment.
In my case all the concrete sub editors had the same types of leaf value editors (I had two different concrete editors one to display and one to edit the same bean type) so I could do something like this to work around this limitation:
interface MyAbstractEditor1 extends Editor<MyBean>
{
LeafValueEditor<String> description();
}
// or as an alternative
abstract class MyAbstractEditor2 implements Editor<MyBean>
{
#UiField protected LeafValueEditor<String> name;
}
class MyConcreteEditor extends MyAbstractEditor2 implements MyAbstractEditor1
{
#UiField TextBox description;
public LeafValueEditor<String> description()
{
return description;
}
// super.name is bound to a TextBox using UiBinder :)
}
Now GWT finds the subeditors in the abstract base class and in both cases I get the corresponding fields name and description populated and flushed.
Unfortunately this approach is not suitable when the concrete subeditors have different values in your bean structure to edit :(
I think this is a bug of the editors framework GWT code generation, that can only be solved by the GWT development team.
Isn't the fundamental problem that the binding happens at compile time so will only bind to QuestionDataProxy so won't have sub-type specific bindings? The CompositeEditor javadoc says "An interface that indicates that a given Editor is composed of an unknown number of sub-Editors all of the same type" so that rules this usage out?
At my current job I'm pushing to avoid polymorphism altogether as the RDBMS doesn't support it either. Sadly we do have some at the moment so I'm experimenting with a dummy wrapper class that exposes all the sub-types with specific getters so the compiler has something to work on. Not pretty though.
Have you seen this post: http://markmail.org/message/u2cff3mfbiboeejr this seems along the right lines.
I'm a bit worried about code bloat though.
Hope that makes some sort of sense!

GWT Widget.addHandler

I am trying to utilize Widget.addHandler(). However, the handler never gets called. Below is my sample code. What do I need to change to fix this?
My Handler Implementation:
public class CustomMouseMoveHandler
extends GwtEvent.Type<MouseMoveHandler>
implements MouseMoveHandler
{
#Override
public void onMouseMove(MouseMoveEvent event) {
System.out.println("----> onMouseMove.");
}
}
My EntryPoint.OnModuleLoad():
ContentPanel cp = new ContentPanel();
cp.setHeaderVisible(false);
cp.setHeight(com.google.gwt.user.client.Window.getClientHeight());
CustomMouseMoveHandler handler = new CustomMouseMoveHandler();
cp.addHandler(handler, handler);
RootPanel.get().add(cp);
/////
Added on 7/1/2011.
The following complete GWT simple code does not work either (with Jason's hint applied). Please help me out. Thanks
package tut.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GwtHandler implements EntryPoint, MouseMoveHandler {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
TextArea comp = new TextArea();
comp.setSize("200px", "200px");
comp.setText("Testing Text");
comp.addHandler(this, MouseMoveEvent.getType());
RootPanel.get().add(comp);
}
#Override
public void onMouseMove(MouseMoveEvent event) {
com.google.gwt.user.client.Window.alert("onMouseMove");
}
}
GwtEvent.Type is used to dispatch events based on an event specific and unique object (object equality - == - is used to match event types). Passing your CustomMouseMoveHandler as the Type to addHandler indicates an event type other than that used for MouseMoveEvents (Indeed in this case every CustomMouseMoveHandler would be assigned to a different event Type since each object is different).
Instead of extending GwtEvent.Type<MouseMoveHandler> in your handler you need to get the event Type from MouseMoveEvent itself (using the static getType() method).
Don't extend GwtEvent.Type in your CustomMouseMoveHandler:
public class CustomMouseMoveHandler
implements MouseMoveHandler
{
...
}
And to add the handler:
cp.addDomHandler(handler, MouseMoveEvent.getType());
DomEvents have to be registered using addDomHandler, or you have to sinkEvents for their event type. addDomHandler is a shortcut for sinkEvents+addHandler.
Here's how I solved my problem. I wanted to add handlers to a NumberLabel. This is what worked:
final NumberLabel<Long> label = new NumberLabel<Long>();
label.setValue(2000l);
label.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
MouseOverHandler handler = new MouseOverHandler() {
public void onMouseOver(MouseOverEvent event) {
System.out.println("mouse over");
}
};
Widget widget = label.asWidget();
widget.addDomHandler(handler, MouseOverEvent.getType());
Treating is as a Widget did the trick.
By the way, System.out.println worked.