Data stores and a funky new interface feature

View: New views
6 Messages — Rating Filter:   Alert me  

Data stores and a funky new interface feature

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


So DWR how has a fairly fully functioning Dojo data store. We're a gnats whisker away from having a store that DWR synchronizes across the server and any browsers viewing the store. It supports sorting, filtering, writing and (in theory) asynchronous updates.
If you sync to HEAD, ant war, run the jetty-demo launcher and visit http://localhost:8080/dwr/widgets/dojo-demo.html you should see how we're doing.

This will be more interesting when it's finished.

However a few cool new features fell out of it today.

STEP 1: Serializing a function

Javascript:

function foo(msg) {
  alert(msg);
}

function callback() {
  alert("Function installed");
}

Remote.method(foo, callback);

Java:

public class Remote {
    public void method(JavascriptFunction foo) {
        this.foo = foo;
    }

    public void calledLater() {
        foo.execute("Functions can now be 'serialized' to the server");
    }

    private JavascriptFunction foo;
}

To note: foo is being passed by reference to the server for later execution. The foo object on the server can be executed as many times as you like. When you call foo.close() then DWR will forget about the function in the client.

STEP 2: Passing and object by reference

Javascript:

function Bar() {
  // Tell DWR we want to pass this by reference
  this.$dwrByRef;
}

Bar.prototype.alert = function(msg) {
  alert(msg);
};

var bar = new Bar();

Remote2.method(bar, callback);

Java:

public class Remote2 {
    public void method(JavascriptObject bar) {
        this.bar = bar;
    }

    public void calledLater() {
        bar.execute("alert", "Objects can now be passed by reference to the server");
    }

    private JavascriptObject bar;
}

To note: This is very similar to the first case, except that we're passing objects by reference rather than functions. JavascriptObject has execute() and close() methods like JavascriptFunction, but also a set() method to set attributes of the object.
The this.$dwrByRef; is needed so DWR knows to pass by reference and not by value. It's possible that we could hack the generated interface code to prompt DWR to know where a byRef is expected, but I think this could get mixed up with potential future function overloading support so I've left is as is.

STEP 3: Remote interface implementation

Java:

public interface BazListener {
  void alert(String msg);
}

Javascript:

function BazListener() {
  this.$dwrByRef;
}

BazListener.prototype.alert = function(msg) {
  alert(msg);
};

var bl = new BazListener();

Remote3.method(bl);

Java:

public class Remote3 {
    public void method(BazListener bl) {
        this.bl = bl;
    }

    public void calledLater() {
        bl.alert("And the objects can dynamically implement interfaces!");
    }

    private BazListener bl;
}

To note: Type safety on the Java side, but clearly not on the Javascript side. If you pass an object that doesn't have an alert method, then it will fail at runtime.
We *could* have DWR export the interface definition, but it's only useful as documentation really.


Right after I finished step 3, I deleted nearly as much code from the data store implementation, as it took me to implement the features above.

Joe.


Re: Data stores and a funky new interface feature

by XMaNIaC :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Joe,

I've started to look into this in my quest to rewrite IWebMvc and I'm having some problems. The demo page shows an error: Method not found. And I can see this trace in Eclipse:

2008-09-19 19:17:02.939::INFO:  #### Initializing context: /dwr
2008-09-19 19:17:02.986::INFO:  Visit http://localhost:8080/dwr/ to get started.
2008-09-19 19:17:02.01::INFO:  jetty-6.1.10
2008-09-19 19:17:02.189::INFO:  NO JSP Support for /dwr, did not find org.apache.jasper.servlet.JspServlet
19-sep-2008 19:17:06 org.directwebremoting.impl.StartupUtil logStartup
INFO: Starting: DwrServlet v3.0.0.110.dev on jetty-6.1.10 / JDK 1.6.0_07 from Sun Microsystems Inc. at /dwr
19-sep-2008 19:17:06 org.directwebremoting.servlet.UrlProcessor afterContainerSetup
GRAVE: Discarding non Handler for url:/jsonp/
19-sep-2008 19:17:06 org.directwebremoting.util.LocalUtil setParams
ADVERTENCIA: Error setting class=com.example.dwr.address.AddressLookup on org.directwebremoting.create.NewCreator
java.lang.IllegalArgumentException: Class not found: com.example.dwr.address.AddressLookup
at org.directwebremoting.create.NewCreator.setClass(NewCreator.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.directwebremoting.util.LocalUtil.setProperty(LocalUtil.java:605)
at org.directwebremoting.util.LocalUtil.setParams(LocalUtil.java:564)
at org.directwebremoting.impl.DefaultCreatorManager.addCreator(DefaultCreatorManager.java:73)
at org.directwebremoting.impl.DwrXmlConfigurator.loadCreate(DwrXmlConfigurator.java:275)
at org.directwebremoting.impl.DwrXmlConfigurator.loadAllows(DwrXmlConfigurator.java:225)
at org.directwebremoting.impl.DwrXmlConfigurator.configure(DwrXmlConfigurator.java:171)
at org.directwebremoting.impl.StartupUtil.configureFromDefaultDwrXml(StartupUtil.java:577)
at org.directwebremoting.impl.StartupUtil.configureContainerFully(StartupUtil.java:686)
at org.directwebremoting.servlet.DwrServlet.configureContainer(DwrServlet.java:110)
at org.directwebremoting.servlet.DwrServlet.init(DwrServlet.java:73)
at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:256)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:612)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:139)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:510)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:222)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.directwebremoting.server.jetty.JettyLauncherBase.start(JettyLauncherBase.java:124)
at org.directwebremoting.server.jetty.JettyDemoLauncher.main(JettyDemoLauncher.java:32)
Caused by: java.lang.ClassNotFoundException: com.example.dwr.address.AddressLookup
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:375)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
at org.directwebremoting.util.LocalUtil.classForName(LocalUtil.java:975)
at org.directwebremoting.create.NewCreator.setClass(NewCreator.java:36)
... 28 more
19-sep-2008 19:17:06 org.directwebremoting.impl.DefaultCreatorManager addCreator
GRAVE: Creator: 'NewCreator[null]' for null.js is returning null for type queries.
2008-09-19 19:17:06.436::INFO:  Started SelectChannelConnector@...:8080
19-sep-2008 19:17:37 org.directwebremoting.extend.Call findMethod
ADVERTENCIA: No methods called class org.directwebremoting.export.Data.viewRegion' are applicable for the passed parameters.
19-sep-2008 19:21:13 org.directwebremoting.extend.Call findMethod

What's the state of this as of today?

Regards

On Thu, Jul 10, 2008 at 9:55 PM, Joe Walker <joe@...> wrote:

So DWR how has a fairly fully functioning Dojo data store. We're a gnats whisker away from having a store that DWR synchronizes across the server and any browsers viewing the store. It supports sorting, filtering, writing and (in theory) asynchronous updates.
If you sync to HEAD, ant war, run the jetty-demo launcher and visit http://localhost:8080/dwr/widgets/dojo-demo.html you should see how we're doing.

This will be more interesting when it's finished.

However a few cool new features fell out of it today.

STEP 1: Serializing a function

Javascript:

function foo(msg) {
  alert(msg);
}

function callback() {
  alert("Function installed");
}

Remote.method(foo, callback);

Java:

public class Remote {
    public void method(JavascriptFunction foo) {
        this.foo = foo;
    }

    public void calledLater() {
        foo.execute("Functions can now be 'serialized' to the server");
    }

    private JavascriptFunction foo;
}

To note: foo is being passed by reference to the server for later execution. The foo object on the server can be executed as many times as you like. When you call foo.close() then DWR will forget about the function in the client.

STEP 2: Passing and object by reference

Javascript:

function Bar() {
  // Tell DWR we want to pass this by reference
  this.$dwrByRef;
}

Bar.prototype.alert = function(msg) {
  alert(msg);
};

var bar = new Bar();

Remote2.method(bar, callback);

Java:

public class Remote2 {
    public void method(JavascriptObject bar) {
        this.bar = bar;
    }

    public void calledLater() {
        bar.execute("alert", "Objects can now be passed by reference to the server");
    }

    private JavascriptObject bar;
}

To note: This is very similar to the first case, except that we're passing objects by reference rather than functions. JavascriptObject has execute() and close() methods like JavascriptFunction, but also a set() method to set attributes of the object.
The this.$dwrByRef; is needed so DWR knows to pass by reference and not by value. It's possible that we could hack the generated interface code to prompt DWR to know where a byRef is expected, but I think this could get mixed up with potential future function overloading support so I've left is as is.

STEP 3: Remote interface implementation

Java:

public interface BazListener {
  void alert(String msg);
}

Javascript:

function BazListener() {
  this.$dwrByRef;
}

BazListener.prototype.alert = function(msg) {
  alert(msg);
};

var bl = new BazListener();

Remote3.method(bl);

Java:

public class Remote3 {
    public void method(BazListener bl) {
        this.bl = bl;
    }

    public void calledLater() {
        bl.alert("And the objects can dynamically implement interfaces!");
    }

    private BazListener bl;
}

To note: Type safety on the Java side, but clearly not on the Javascript side. If you pass an object that doesn't have an alert method, then it will fail at runtime.
We *could* have DWR export the interface definition, but it's only useful as documentation really.


Right after I finished step 3, I deleted nearly as much code from the data store implementation, as it took me to implement the features above.

Joe.



Re: Data stores and a funky new interface feature

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Sep 19, 2008 at 6:28 PM, Jose Noheda <jose.noheda@...> wrote:
Hi Joe,

I've started to look into this in my quest to rewrite IWebMvc and I'm having some problems. The demo page shows an error: Method not found. And I can see this trace in Eclipse:
...
What's the state of this as of today?

Not used as regularly as it was due to our shiny new test framework ;-)

I've just run it up and fixed a few things.

One that requires some attention:
Mike - the generated scripts now assume that engine.js has been loaded before the interface scripts, could we have it check for the existance of _mappedClasses before we use it?
I have a feeling that this is going to require changes to engine.js too.
 
Joe.


RE: Data stores and a funky new interface feature

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Joe wrote:

One that requires some attention:
Mike - the generated scripts now assume that engine.js has been loaded before the interface scripts, could we have it check for the existance of _mappedClasses before we use it?
I have a feeling that this is going to require changes to engine.js too.
Ah, you're absolutely right Joe. I have to admit that I assumed that engine.js would always have to be loaded before the interface scripts anyway, so I didn't cover the opposite case. But it should be an easy fix; just add some "define if not already defined" logic for dwr, dwr.engine and dwr.engine._mappedClasses to both interface scripts and engine.js. (Shout if you'd like me to do it.)
 
Best regards
Mike

Re: Data stores and a funky new interface feature

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Just done it.

Joe.

On Wed, Sep 24, 2008 at 6:00 PM, Mike Wilson <mikewse@...> wrote:
Joe wrote:

One that requires some attention:
Mike - the generated scripts now assume that engine.js has been loaded before the interface scripts, could we have it check for the existance of _mappedClasses before we use it?
I have a feeling that this is going to require changes to engine.js too.
Ah, you're absolutely right Joe. I have to admit that I assumed that engine.js would always have to be loaded before the interface scripts anyway, so I didn't cover the opposite case. But it should be an easy fix; just add some "define if not already defined" logic for dwr, dwr.engine and dwr.engine._mappedClasses to both interface scripts and engine.js. (Shout if you'd like me to do it.)
 
Best regards
Mike


RE: Data stores and a funky new interface feature

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

While having a quick look at your updates it occured to me that the same thing could happen if <dto>.js or dtoall.js are included first. Currently the problem is only solved for interfaces so you may want to apply the same fix to the other two?
Also, I believe the
    dwr.engine = { };
assignment at top of engine.js needs to be guarded by an "if not defined" thingie.
Best regards
Mike


From: joseph.walker@... [mailto:joseph.walker@...] On Behalf Of Joe Walker
Sent: den 25 september 2008 12:06
To: users@...
Subject: Re: [dwr-user] Data stores and a funky new interface feature


Just done it.

Joe.

On Wed, Sep 24, 2008 at 6:00 PM, Mike Wilson <mikewse@...> wrote:
Joe wrote:

One that requires some attention:
Mike - the generated scripts now assume that engine.js has been loaded before the interface scripts, could we have it check for the existance of _mappedClasses before we use it?
I have a feeling that this is going to require changes to engine.js too.
Ah, you're absolutely right Joe. I have to admit that I assumed that engine.js would always have to be loaded before the interface scripts anyway, so I didn't cover the opposite case. But it should be an easy fix; just add some "define if not already defined" logic for dwr, dwr.engine and dwr.engine._mappedClasses to both interface scripts and engine.js. (Shout if you'd like me to do it.)
 
Best regards
Mike

LightInTheBox - Buy quality products at wholesale price