1. The tokens are big, they include the full path to the class, so all
packages and the name of the class. It's a lot. In our case, it also
exposes the name of the contractor to the user of the application.
2. Tokens in RequestFactory only work with Record based classes. I
think that's a shame. Will another facility supplement this? Because
if tokens from gwt will only support Record, why even bother with
ProxyPlace? Just make a goTo method in PlaceController that takes a
record. I would prefer to have tokens for a place directly. I think
that can be accomplished by having multiple place tokenizers however,
one per place.
3. Ultimately, I don't think the assumption that a record type is 1:1
to an activity. The mapper stuff allows for this but is yet more
code.
4. It's a lot harder than it seems to always have a record ready to
go. Especially coming from gwt-presenter were we always try to just
keep a numeric id.
5. I think the Place class getting support for a collection of arguments, i.e.,
setArgument(String, String);
String getArgument(String);
clearArguments();
and more importantly, parseArguments(String s); so that we can pass in
a string from the PlaceTokenizer.getPlace() after we've removed the
prefix would be most helpful and be applicable to most.
thank you,
1. The tokens are big, they include the full path to the class, so all
packages and the name of the class. It's a lot. In our case, it also
exposes the name of the contractor to the user of the application.
I am talking about the new methods in RequestFactory that provide
support for bookmarble locations based on Records. So for
UserAccountRecord, requestFactory.getToken(record); will produce a
string
com.yourcompany.records.UserAccountRecord-id
which is big
> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors
No it's not. This is the tokens returns by RequestFactory based on
your record classes. The *Place objects that you use have no bearing
on what these methods produce. The place tokenizer has nothing to do
with this other that it uses RequestFactory to get these tokens and
get back a Class<?> back from the tokens.
>
>> 2. Tokens in RequestFactory only work with Record based classes. I
>> think that's a shame. Will another facility supplement this? Because
>> if tokens from gwt will only support Record, why even bother with
>> ProxyPlace? Just make a goTo method in PlaceController that takes a
>> record. I would prefer to have tokens for a place directly. I think
>> that can be accomplished by having multiple place tokenizers however,
>> one per place.
>
> I don't understand. Of course RequestFactory only deals with Records,
> but that's totally independent from Places and History tokens (well,
Why "of course"? RequestFactory means a factory of "requests", not a
factory of "records". You can use RequestFactory to fire requests
that don't have any records, e.g.,
RequestObject<Long> getMeALongNotUsingARecord(Long param1, Long param2);
no request here.
> RequestFactory can give you tokens for your records, but yet again,
> that's only if you *want* to use that, which you'll do by using the
> provided Proxy{,List}Place.Tokenizer).
Again, hence my objection.
> I haven't seen any limitation in PlaceHistoryHandler forbidding its
> use with places other the the provided Proxy{,List}Place; of course,
> for those places, you'd have to provide your own PlaceTokenizer.
That's what I am currently doing.
>
>> 3. Ultimately, I don't think the assumption that a record type is 1:1
>> to an activity. The mapper stuff allows for this but is yet more
>> code.
>
> There's no such assumption AFAICT. And actually, for a given record
> type, ProxyPlace gives you 3 different places, and ProxyListPlace an
> additional one. You're then free to map those places to activities in
> your ActivityMapper. And of course you're free to not use Proxy{,List}
> Place at all.
There's is such an assumption in ProxyPlace because it requires a
record but more to the point because of AbstractRecordEditActivity.
If you have a user record and you want to edit your record, your user
record edit activity should be a function of your user privileges.
Currently, the only way to do this is to use activity mappers or use
multiple places. Again, I stated this.
The other reason why that assumption is made is that
AbstractRecordEditActivity requires a record now. Currently, there is
no way to build a proxy record, i.e., a record where all fields are
stale but the id, in code. You would need to create a string token
manually which assumes that:
a) You know what the string token looks like, append the id, and pass
it on to RequestFactory.
b) The string token algorithm will not change from version to version.
Already on this thread, we can see that it will already change.
c) or, fire the list request before you create the
AbstractRecordEditActivity, get a fresh record from the server and
have AbstractRecordEditActivity fire a list yet again once it's
constructed.
Due to AbstractRecordEditActivity, we're pretty much forced to carry
around records in the place.
>
>> 5. I think the Place class getting support for a collection of arguments, i.e.,
>>
>> setArgument(String, String);
>> String getArgument(String);
>> clearArguments();
>>
>> and more importantly, parseArguments(String s); so that we can pass in
>> a string from the PlaceTokenizer.getPlace() after we've removed the
>> prefix would be most helpful and be applicable to most.
>
> Please NOOOO!!! That's the role of the PlaceTokenizer. If you want a
> generic place with String "arguments" and a generic tokenizer making
> look like e.g. a query-string in history tokens, you can do it already
> but please don't make it a default!
> You shouldn't do getArgument("foo"), you should instead have a
> specific Place subclass giving you a getFoo().
Because you're assuming that one place and one list place is
sufficient for all needs and I don't think it is. You have common
code dealing with arguments that will always be there. We can have a
base place that adds it and does it on our own but would still be
practical to have in Place since it's currently empty.
The argument for these common methods for arguments is that at the
very least, they have to be placed on the url bar and be parsed back.
That is common to all places.
Furthermore, yes, getFoo() instead of getArgument("foo") is nice but
a) It doesn't mean a base place with getArgument("foo") can't have a
concrete class that has getFoo() that does the proper construction
b) With ActivityMapper no longer being a generic, getting to getFoo()
means downcasting all over the code.
To address your comment that this is the role of PlaceTokenizer, it
is, but currently, there is no standard PlaceTokenizer that handles
standard query parameters. And there can't be one unless it has an
interface in which it get and set place arguments into the place
itself, hence the argument for get/setArgument in Place.
> It may sound a bit harsh but you've IMO been very badly influenced by
> gwt-presenter.
Is that really necessary? We're building out a real, big application
and giving back feedback.
I know, I responded to your comment.
> 2. I added that this is only used by ProxyPlace.Tokenizer (and I
> really see RequestFactory.getToken/getProxy as helper methods for
> ProxyPlace.Tokenizer), that you're free to *not* use.
> I understand this is feedback on RequestFactory.getToken return values
> (though it wasn't very clear) but yet again, Ray C responded to your
> complaint and in case you'd like to deliver a version of your app
> without waiting for this to be fixed/enhanced, you can workaround it
> by providing your own PlaceTokenizer.
I don't see what this has to do with anything. We do have our own
place tokenizer but it doesn't mean there isn't value in being able to
get a history token from RequestFactory for something that isn't a
record. Right now, anything that has a getId() would be sufficient
>
>> >> 2. Tokens in RequestFactory only work with Record based classes. I
>> >> think that's a shame. Will another facility supplement this? Because
>> >> if tokens from gwt will only support Record, why even bother with
>> >> ProxyPlace? Just make a goTo method in PlaceController that takes a
>> >> record. I would prefer to have tokens for a place directly. I think
>> >> that can be accomplished by having multiple place tokenizers however,
>> >> one per place.
>>
>> > I don't understand. Of course RequestFactory only deals with Records,
>> > but that's totally independent from Places and History tokens (well,
>>
>> Why "of course"? RequestFactory means a factory of "requests", not a
>> factory of "records". You can use RequestFactory to fire requests
>> that don't have any records, e.g.,
>>
>> RequestObject<Long> getMeALongNotUsingARecord(Long param1, Long param2);
>>
>> no [record] here.
>
> Yes, you can, but (correct me if I'm wrong):
> 1. anything more complex than a primitive type or its wrapper class, a
> Date, or a String has to be a Record
I would use a Record yes but it doesn't have to be.
> 2. you'd have to make your own Place and PlaceTokenizer for those, so
> why bother asking RequestFactory for a token? (have I said I do think
> getToken/getProxy are really "just" helpers for
> ProxyPlace.Tokenizer? ;-) )
But why should they be limited to ProxyPlace? You understand this is
a toolkit and it's trying to do work that we would otherwise need to
do? If they are are helpers only for Proxy*Place and only
Proxy*Place, why make them so visible by having them in
RequestFactory?
> You used the expression "tokens from GWT", which I understood as
> "history management", which *of course* are not limited to records; so
> there's really a reason to "bother" with ProxyPlace.
> Having a goTo(Record) in PlaceController would make it depend on
> RequestFactory, which would be bad design (as long as you don't use
> ProxyPlace and ProxyListPlace, you can very well use PlaceController
> and PlaceHistoryHandler without using RequestFactory at all).
> I'd add that having a PlaceTokenizer *per place* is by-design; this is
> very different from gwt-presenter which has a single PlaceFormatter to
> handle all places.
A place tokenizer per place is a lot of boiler plate code. Even if
you try to minimize the impact. Again, it's clear to me that the goal
of 2.1 is developer productivity. Hence, I don't think this follows
the spirit of it.
The comment on goTo taken a record is not me asking you to explain to
me why it's bad design or me asking to actually have goTo take a
record. I'm announcing it to make a point, where things have been
made too narrow for real usage.
>
>> > I haven't seen any limitation in PlaceHistoryHandler forbidding its
>> > use with places other the the provided Proxy{,List}Place; of course,
>> > for those places, you'd have to provide your own PlaceTokenizer.
>>
>> That's what I am currently doing.
>
> have you tried using ProxyPlace (provided what it represents –an
> "operation" on a particular record– suits your needs) with a custom
> PlaceTokenizer?
I did and failed. ProxyPlace means assuming 1:1 between record and
activity. We have a user record. So edit on a user record means
either my preferences, other user or patient. Again, before you
repeat what I said before in a different way, I did state this and
stated how you could accomplish this using ProxyPlace and
ActivityMapper. The feedback was that it's too cumbersome to do it
this way hence we continued to use multiple places.
I don't know what you're trying to say here, I'm not even going to try
to respond, it's too long
>
>> The other reason why that assumption is made is that
>> AbstractRecordEditActivity requires a record now. Currently, there is
>> no way to build a proxy record, i.e., a record where all fields are
>> stale but the id, in code.
>
> Yes you can: use requestFactory.create()
> http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/app/place/AbstractRecordListActivity.java#125
This produces a record who's id is set to a future from the future id
generator. You have no way of setting the value of the id of the
newly created record.
>
> Yes, ActivityMappers are expected to be made of if/else around
> instanceof tests. And actually, Places are only expected to be used
and that is to be considered good design?
> from ActivityMappers (the ActivityMapper will setup the Activity with
> the appropriate "state", so an Activity doesn't need to know the
> Place, and I'd even say it shouldn't know about places at all, except
> for instantiating them to give them to PlaceController.goTo).
> See for example
> http://code.google.com/p/google-web-toolkit/source/browse/trunk/bikeshed/src/com/google/gwt/sample/expenses/gwt/client/ExpensesDetailsActivities.java
> (which only deals with ProxyPlace, but still does a check at the very
> start to make sure it doesn't deal with anything else; and the
> ExpensesEntityTypesProcessor (this is an implementation detail of apps
> generated by Roo; I guess it makes them easier to maintain by Roo when
> you add record types) does the same with the record types:
> http://code.google.com/p/google-web-toolkit/source/browse/trunk/bikeshed/src/com/google/gwt/sample/expenses/gwt/request/ExpensesEntityTypesProcessor.java#67
>
Again, I don't know why you keep me pointed out to the basics
considering I told you we have a large app that we're building with
GWT head.
>> To address your comment that this is the role of PlaceTokenizer, it
>> is, but currently, there is no standard PlaceTokenizer that handles
>> standard query parameters.
>
> And I don't think there should be. Though I think it should be easy to
> build one, and "frameworks" like gwt-presenter would probably given
> one to you.
>
Again, you do understand that GWT is a framework? We've written one,
the feedback is that I believe it should be provided, feel free to
disagree.
again, snipping more long things,
>
>> > It may sound a bit harsh but you've IMO been very badly influenced by
>> > gwt-presenter.
>>
>> Is that really necessary? We're building out a real, big application
>> and giving back feedback.
>
> I'm sorry, this was more directed to gwt-presenter than to you
> personnaly. As I said, I really dislike how gwt-presenter deals with
> places, and I think it doesn't "get" the concept of places.
> The reason I'm supporting GWT's approach is that the one I developed a
> year ago for our own apps is very similar (minus the notion of
> activities, but at the lower-level of Place, PlaceController,
> PlaceChangeEvent, and now PlaceTokenizer, there are many things in
> common).
So that makes it OK to ridicule the hard work that the gwt-presenter
maintainer did? He stepped up after Google I/O 2009 and that's a lot
more than most people can say and just for the sake of full
disclosure, I do not know him. Furthermore, it helped guide the
design of gwt 2.1 by providing use cases of what people were doing and
trying to do. So far, I feel the place management work in GWT 2.1 is
good but could nonetheless gain insight into these comments and
gwt-presenter. I would also say the large if-else statements of
instanceof on places is not something I look forward to and have
adopted a visitor pattern to take that out of the equation. In any
case, feel free to continue this thread but I'm done.