Server-only functions

86 views
Skip to first unread message

Christophe

unread,
Aug 26, 2009, 2:52:40 PM8/26/09
to Google Web Toolkit
I find the client-server distinction too coarse to work with. The
strength of gwt is at least partly in the RPC mechanism and passing
full classes.

I was therefore wondering. Isn't it possible to declare a specific
function or inner class if that's easier to only be accessible on the
server side ? I realize this poses all sorts of problems for variables
and deciding whether or not something gets serialized, but I'd be most
happy if the compiler just threw those problems in my face and
expected me to fix them.

I realize server-side there can be only one class definition. But I'd
like to "opt-out" of translating compiling specific functions, and
just get an error message if that function is used by any client code.

What I'm really looking for is something like this, and this would be
an example usage :

class getServerTimeCommand implements Command {
Date d;

@ServerOnly
public void execute() {
d = new Date();
}

// whoops no ServerOnly, yet calls a ServerOnly function
public void doItAnyway() {
execute(); // ERROR, attempting to call serverside code from
within client code
}
}

Is it possible to do something like this ? If not, would it be
possible to implement it ? It would be extremely handy for reducing
the number of classes needed in RPC. I basically want the ability to
say about certain class members "please don't serialize this".

I realize that for certain data fields you have problems, since not
passing them to the client side requires keeping track of references,
however I think you can avoid that problem by allowing only functions
to do this. This would also enormously simplify the usage of various
java tools both server- and client-side.

Christophe
--
"Flying is simply learning how to throw yourself at the ground and
miss." - Douglas Adams

Thomas Broyer

unread,
Aug 26, 2009, 6:42:18 PM8/26/09
to Google Web Toolkit


On 26 août, 20:52, Christophe <christophe.devri...@gmail.com> wrote:
> I find the client-server distinction too coarse to work with. The
> strength of gwt is at least partly in the RPC mechanism and passing
> full classes.

...and those classes should generally be "DTOs" (a.k.a. "value
objects") and thus shouldn't have any embedded logic (even less some
logic that's only available on one side and not the other!)
(otherwise, you would be doing someObject.save(callback), not
myService.save(someObject, callback) !)

> I was therefore wondering. Isn't it possible to declare a specific
> function or inner class if that's easier to only be accessible on the
> server side ? I realize this poses all sorts of problems for variables
> and deciding whether or not something gets serialized, but I'd be most
> happy if the compiler just threw those problems in my face and
> expected me to fix them.

See http://code.google.com/p/google-web-toolkit/issues/detail?id=3769

Christophe

unread,
Aug 26, 2009, 8:03:02 PM8/26/09
to Google Web Toolkit
On Aug 27, 12:42 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> ...and those classes should generally be "DTOs" (a.k.a. "value
> objects") and thus shouldn't have any embedded logic (even less some
> logic that's only available on one side and not the other!)
> (otherwise, you would be doing someObject.save(callback), not
> myService.save(someObject, callback) !)

Well, no, actually. The example I really want to use was the "Command"
interface above. It would mainly allow me to keep the code interface
(to be used client-side) and the code itself would be in the same
class. Then I'd have a RemoteService where you can pass a "command"
and the server component simply calls commandfromclient.execute().
Something like this :

class SomeCommand {
private SomeType param1;
private SomeType param2;

private SomeType returnval;

public SomeCommand(some parameters) {
}

@ServerOnly
public void execute() {
// actually do what's requested, using all available server
resources
// database updates, whatever
returnval = someReturnVal;
}

// suggested at google I/O
@ServerOnly
public void undo() {
...
}
}

Note that implementing this, using 3 classes instead of 1 was actually
suggested as good practice in the google I/O session "Google App
Architecture Best Practices" ( http://code.google.com/events/io/sessions/GoogleWebToolkitBestPractices.html
). Why do I need to implement 3 classes in order to do this ? In
addition to needing 3 classes, they also have to be located in
radically different parts of the application, despite the obvious
relationship. Why do I need an interface PER command ? That makes no
sense in the design, why should it be forced on me at implementation ?

JDO's wouldn't be that easy to implement even with this facility since
you need to keep state (like database references, transactions, ...),
and obviously state and serialization don't go all that well together.
It'd be useful though, but would still require major surgery.

The problem I'd like to deal with in this interface is that any code
that the client calls and is executed on the server requires modifying
at the very least 3 classes (and an xml file and a static declaration
in your "main" class if you wish to give it a different path for
clarity), that have radically different functions and locations. I
understand all 3 classes, and I agree all three have to exist, it's a
good design. But they're all "plumbing" classes, having nothing to do
with the application logic. It'd be great to have a way to have client-
side logic and server-side logic in the same class, clearly separated
by using annotations.

The reverse of this feature actually exists in the gwt javascript
compiler : making sure that some methods get translated to javascript,
no matter what. This feature is embedded in the compiler and is a
class-level annotation called @ArtificialRescue where you're supposed
to pass comma-separated lists of items to "rescue" : variables,
methods and something else. It is used extensively (though it seems
not very well documented)

If I were to create a patch that followed the @ArtificialRescue
principle but with a "@ServerOnly" annotation name that was valid on a
method and submitted it, do you think it has a chance of getting
accepted ?

Kind regards,

Christophe

Asko Saura

unread,
Sep 16, 2009, 3:13:11 AM9/16/09
to Google Web Toolkit
On Aug 27, 3:03 am, Christophe <christophe.devri...@gmail.com> wrote:
> If I were to create a patch that followed the @ArtificialRescue
> principle but with a "@ServerOnly" annotation name that was valid on a
> method and submitted it, do you think it has a chance of getting
> accepted ?

I don't know about the GWT development team, but I'm working on the
same thing.

I've got a bunch of DTOs which include some housekeeping methods used
by another framework, which I use on the server side. Getting to reuse
these objects on the client side would be absolutely great. I can't
use them now, because they happen to include some server-only
dependencies in methods.

My own plan is to add a "@ServerOnly" annotation on those few methods.

Sripathi Krishnan

unread,
Sep 16, 2009, 10:22:19 AM9/16/09
to google-we...@googlegroups.com
Its up to you to implement it, but I would advise you not to do so.

Assume you have a DTO which includes two functions - void serverSideOnly() and void clientSideFunction().

You would now have to guarantee that clientSideFunction() doesn't somehow call serverSideOnly()  -- because that would not work in javascript.

And supposing you end up guaranteeing the above, it means you have two sets of functions in your class which don't speak to each other. Which means they have no business being together in the same class. You could just make a ServerSideDTO that extends from your ClientSideDTO and add the extra methods.

--Sri


2009/9/16 Asko Saura <asko....@gmail.com>

Asko Saura

unread,
Sep 17, 2009, 6:41:35 AM9/17/09
to Google Web Toolkit
On Sep 16, 5:22 pm, Sripathi Krishnan <sripathi.krish...@gmail.com>
wrote:
> Its up to you to implement it, but I would advise you not to do so.
>
> Assume you have a DTO which includes two functions - void serverSideOnly()
> and void clientSideFunction().
>
> You would now have to guarantee that clientSideFunction() doesn't somehow
> call serverSideOnly()  -- because that would not work in javascript.
>
> And supposing you end up guaranteeing the above, it means you have two sets
> of functions in your class which don't speak to each other. Which means they
> have no business being together in the same class. You could just make a
> ServerSideDTO that extends from your ClientSideDTO and add the extra
> methods.

I understand the issues and I've built prototypes on various
workarounds. The other stuff I do on my system depends on the DTOs
being the way they are. They are, in fact, auto-generated for use with
another framework. Refactoring them to make sense in this case is more
expensive for me than tweaking GWT is.

I realize that "GWT people" don't want this, precisely for the reasons
you cited. It's poor design and breaks assumptions that they currently
feel comfortable holding. From my viewpoint, GWT is a minor UI in my
bigger system and if something's got to give, it's GWT design
integrity. I'm a user. I know what I want. I understand that GWT
people may not want me to do it.

David Given

unread,
Sep 17, 2009, 8:25:17 AM9/17/09
to google-we...@googlegroups.com
Sripathi Krishnan wrote:
[...]

> And supposing you end up guaranteeing the above, it means you have two
> sets of functions in your class which don't speak to each other. Which
> means they have no business being together in the same class. You could
> just make a ServerSideDTO that extends from your ClientSideDTO and add
> the extra methods.

That's not always possible. I have much the same situation, except my
DTOs themselves have a class structure. I end up having this:

CObject
CThing
COtherThing

SObject
SThing
SOtherThing

...where S classes exist on the server and C classes on the client. I
can't have SOtherThing inherit from COtherThing because it needs to
inherit from SThing and Java only supports single inheritance.

As a result I'm having to duplicate quite a lot of logic that's needed
in both class hierarchies. There are solutions to this --- but most of
them involve creating a *third* complete class hierarchy containing the
common logic and delegating functionality to that from the S and C classes.

This isn't a situation where the proposed @ServerOnly annotation would
help --- although I could certainly use it elsewhere --- but you should
be aware that things aren't always as simple as they first seem. You
can't make a programmer's life easier by taking tools away from them.

--
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────

│ "They laughed at Newton. They laughed at Einstein. Of course, they
│ also laughed at Bozo the Clown." --- Carl Sagan

Sumit Chandel

unread,
Sep 21, 2009, 5:47:11 PM9/21/09
to google-we...@googlegroups.com
Hi all,

Thanks for expressing use cases for an @ServerOnly type annotation. I've updated Issue # and forwarded it over to Scott Blum for further review. Feel free to star the issue to keep track of updates.

Issue #3769:

Cheers,
-Sumit Chandel

Asko Saura

unread,
Sep 28, 2009, 3:04:36 AM9/28/09
to Google Web Toolkit
On Sep 16, 10:13 am, Asko Saura <asko.sa...@gmail.com> wrote:
> I've got a bunch of DTOs which include some housekeeping methods used
> by another framework, which I use on the server side. Getting to reuse
> these objects on the client side would be absolutely great. I can't
> use them now, because they happen to include some server-only
> dependencies in methods.
>
> My own plan is to add a "@ServerOnly" annotation on those few methods.

This is what I ended up doing:

"SampleDto" is one of the many DTO classes I use. It includes a few
non-persistent (method-level) dependencies to a server-only framework.
I use a script to autogenerate a source version of SampleDto with all
the server-only stuff left out. Thus, I've got two versions of each
DTO source:

SampleDto.java - for server use
SampleDto.java - for client use

I compile the server versions into .class files. Then I include
a .gwt.xml file describing them as a gwt module and put the .class
files and the client .java files in a jar file.

It seems to work. On the server, I've got access to all the server
functions. On the client, I've got access to the rest. Apparently
(I've not verified it), GWT/RPC works based only on the .java files
set in the gwt module using <source-path/>.

The obvious downside is having to deal with two versions of source.
However, this kind of stuff is very straightforward to automatize; I
don't normally need to see the client-only .java code at all. The
obvious upside is getting to use the same DTO code on the server and
the client without having to build the thing from the ground up based
on GWT constraints.

What have I missed? What are the non-obvious downsides?

bufferings

unread,
Sep 28, 2009, 10:11:41 AM9/28/09
to Google Web Toolkit
On 9月28日, 午後4:04, Asko Saura <asko.sa...@gmail.com> wrote:
> I compile the server versions into .class files. Then I include
> a .gwt.xml file describing them as a gwt module and put the .class
> files and the client .java files in a jar file.

> I compile the server versions into .class files. Then I include
> a .gwt.xml file describing them as a gwt module and put the .class
> files and the client .java files in a jar file.

Why don't you use the super-source?

For example ===

src/xxx/yyy/Sample.gwt.xml
src/xxx/yyy/server/SampleDto.java
super/xxx/yyy/translatable/xxx/yyy/server/SampleDto.java

The "src" is source directory.
The "super" is normal directory.
For both "SampleDto.java", the package declaration is
"xxx.yyy.server".

Sample.gwt.xml with the following contents:
<source path="client" />
<super-source path="translatable" />

then

On the server, "xxx.yyy.server.SampleDto.java" is used.
On the client, "xxx.yyy.translatable.xxx.yyy.server.SampleDto.java" is
used.
===

The super-source brings me the code separation between the client and
the server.
But I think "GWT people" don't want this, too.

I really hope an @ServerOnly type annotation will be supported.

--
buffeirngs

Sumit Chandel

unread,
Sep 28, 2009, 6:20:45 PM9/28/09
to google-we...@googlegroups.com
Hi bufferings,

Using a super-source solution would certainly be a good way to deal with this issue, and is a good recommendation here. The super-src solution is much more explicit than having multiple Java source files around, some sprinkled with @ServerOnly annotations and some not. I believe it makes the application design much clearer and more easily customizable on a per-project basis.

Cheers,
-Sumit Chandel
Reply all
Reply to author
Forward
0 new messages