Tapestry's Simplicity Blues

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Tapestry's Simplicity Blues

Vjeran Marcinko
Hi everyone.

This last post of mine about default bindings, and also some work that I do
currently gave way to little chiming about Tapestry's simplicity (or
complexity), and simplicity in general.... I will try to stress out
importance of simplicity.

Knowledge is good. Gaining knowledge about piece of software such as
Tapestry is good. But there's one bad thing that happens when you gain
knowledge - you easily start to forget how was the time when you didn't have
it. How was to be newbie? And newbies have to learn. They appreciate simple
things. They don't want to subscribe to mailing list to ask about problems.
They want to read UserGuide, a short one, and start working. One has to take
care of newbies, because 70% developers are them.

Tapestry is powerful. But it is quite complex. I know that someone could say
that it's because of different way of thinking than typical request-driven
MVC aproach, but believe me, it's complex. I remember myself beggining with
it 1,5 years ago.

Now that I look at it, one cause of complexity was because of Tapestry's way
to offer multiple ways of doing things.
At first, it looks cool when you get provided with multiple options, but
hey, multiple options take time to learn compared with single option. One
could say that you don't have to learn option that you don't like, but
during development one has to look at other people's stuff, co-workers
stuff, tutorials on the web etc.... And these pieces of software has maybe
picked other option that you didn't, which you have to learn to understand
it. At the end, you have to learn whole Tapestry to be able to handle it
properly.

Here are the examples:
- ActionLink and DirectLink : former is *kind of* deprecated, but not
really, so we still have it in framework
- manual and automatic handling of properties: I hate "abstract" keyword
used for
this, but it's much easier sometimes
- implicit and explicit components
- setting binding values (my last post) in 3 ways
- PageRenderListener and overriding prepareForRender(): both for single
purpose-> pre-render initialization (depends whether it is page or
component)
- Foreach and ListEdit
- manual field validation, or using ValidField in some cases (when working
with text fields)
..and probably some others...

Of course, adding new options made work so much easier in some cases, thus
it was reason to import them into framework. So, you gain more power, but
you gain more complexity. It's maybe best to look through User Guide. If
newbie suddenly comes upon one whole page of documentation, whereas there
was half of it in the last version of software, then you surely have lost
some quality. So sometimes it has to be asked - was it worth it?

Of course, plenty of things become more powerful *and* simplier in new
versions: For component unifying Foreach and ListEdit, removal of
"direction" is totaly awesome, etc...

Inspiration for this post came this morning, when I was writing UserGuidefor
my remoting library that is supose to be distributed to third-party
companies. I thought documentation will be quite short considering that
library is very simple to use. But when I started writing it, I realized I
forgot to include "Logging" section because I assumed everyone knows what
Commons-Logging is. But suddenly I realized that bunch of people in
big-corporate companies, with vanilla programmers, never even heard of it,
thus I needed to include this section. Then more of this things kept coming
in, and I had to force myself to think the way newbie does.

Cheers,
Vjeran



--
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.308 / Virus Database: 266.11.8 - Release Date: 10.5.2005


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Erik Hatcher
Vjeran,

I enjoy your posts and this one was no exception.  You provide a much  
needed refreshing viewpoint on Tapestry.  I converse with Howard  
about complexity on a regular basis.  I won't paraphrase his view,  
but it does contrast with mine.  I feel that complexity leaks, much  
like the age old "abstractions leak" mantra.  The more complex the  
core of Tapestry, the more magic that it contains, the more likely  
that complexity is felt by the programmer trying to build a page.

My most recent struggle is with integrating auto-commit (via Cayenne)  
for all of my listener methods without them having to explicitly have  
a Cayenne dependence and mandating that they individually call the  
Cayenne commit API.  IM'ing with Howard a bit, he gave me some tips  
on how to hook listener methods.  I opted for the simplest one, by  
overriding getListeners() and creating custom IActionListener's  
around the ones provided by Tapestry itself.  This worked great,  
until I hit a page that throws a RedirectException.  So now I have to  
code in the catching of (Page)RedirectException and re-throw it.  I  
don't think it is right to use exceptions for flow control.

Don't get me wrong, folks.  I love Tapestry and it has made my web  
development life more pleasant over the past few years.  Howard is  
brilliant and has done a great service for us all with his creative  
work.

But I struggle with the complexity of it on a daily basis and it does  
get in my way of being as productive as I could.  Any complaints we  
have about it should be taken constructively - if we feel  
passionately enough about it to take the time to post our  
tribulations it means we do care about it.

     Erik


On May 11, 2005, at 3:57 AM, Vjeran Marcinko wrote:

> Hi everyone.
>
> This last post of mine about default bindings, and also some work  
> that I do
> currently gave way to little chiming about Tapestry's simplicity (or
> complexity), and simplicity in general.... I will try to stress out
> importance of simplicity.
>
> Knowledge is good. Gaining knowledge about piece of software such as
> Tapestry is good. But there's one bad thing that happens when you gain
> knowledge - you easily start to forget how was the time when you  
> didn't have
> it. How was to be newbie? And newbies have to learn. They  
> appreciate simple
> things. They don't want to subscribe to mailing list to ask about  
> problems.
> They want to read UserGuide, a short one, and start working. One  
> has to take
> care of newbies, because 70% developers are them.
>
> Tapestry is powerful. But it is quite complex. I know that someone  
> could say
> that it's because of different way of thinking than typical request-
> driven
> MVC aproach, but believe me, it's complex. I remember myself  
> beggining with
> it 1,5 years ago.
>
> Now that I look at it, one cause of complexity was because of  
> Tapestry's way
> to offer multiple ways of doing things.
> At first, it looks cool when you get provided with multiple  
> options, but
> hey, multiple options take time to learn compared with single  
> option. One
> could say that you don't have to learn option that you don't like, but
> during development one has to look at other people's stuff, co-workers
> stuff, tutorials on the web etc.... And these pieces of software  
> has maybe
> picked other option that you didn't, which you have to learn to  
> understand
> it. At the end, you have to learn whole Tapestry to be able to  
> handle it
> properly.
>
> Here are the examples:
> - ActionLink and DirectLink : former is *kind of* deprecated, but not
> really, so we still have it in framework
> - manual and automatic handling of properties: I hate "abstract"  
> keyword
> used for
> this, but it's much easier sometimes
> - implicit and explicit components
> - setting binding values (my last post) in 3 ways
> - PageRenderListener and overriding prepareForRender(): both for  
> single
> purpose-> pre-render initialization (depends whether it is page or
> component)
> - Foreach and ListEdit
> - manual field validation, or using ValidField in some cases (when  
> working
> with text fields)
> ..and probably some others...
>
> Of course, adding new options made work so much easier in some  
> cases, thus
> it was reason to import them into framework. So, you gain more  
> power, but
> you gain more complexity. It's maybe best to look through User  
> Guide. If
> newbie suddenly comes upon one whole page of documentation, whereas  
> there
> was half of it in the last version of software, then you surely  
> have lost
> some quality. So sometimes it has to be asked - was it worth it?
>
> Of course, plenty of things become more powerful *and* simplier in new
> versions: For component unifying Foreach and ListEdit, removal of
> "direction" is totaly awesome, etc...
>
> Inspiration for this post came this morning, when I was writing  
> UserGuidefor
> my remoting library that is supose to be distributed to third-party
> companies. I thought documentation will be quite short considering  
> that
> library is very simple to use. But when I started writing it, I  
> realized I
> forgot to include "Logging" section because I assumed everyone  
> knows what
> Commons-Logging is. But suddenly I realized that bunch of people in
> big-corporate companies, with vanilla programmers, never even heard  
> of it,
> thus I needed to include this section. Then more of this things  
> kept coming
> in, and I had to force myself to think the way newbie does.
>
> Cheers,
> Vjeran
>
>
>
> --
> No virus found in this outgoing message.
> Checked by AVG Anti-Virus.
> Version: 7.0.308 / Virus Database: 266.11.8 - Release Date: 10.5.2005
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Konstantin Ignatyev
Erik Hatcher wrote:

>
> My most recent struggle is with integrating auto-commit (via Cayenne)  
> for all of my listener methods without them having to explicitly have  
> a Cayenne dependence and mandating that they individually call the  
> Cayenne commit API.  IM'ing with Howard a bit, he gave me some tips  
> on how to hook listener methods.  I opted for the simplest one, by  
> overriding getListeners() and creating custom IActionListener's  
> around the ones provided by Tapestry itself.  This worked great,  
> until I hit a page that throws a RedirectException.  So now I have to  
> code in the catching of (Page)RedirectException and re-throw it.  I  
> don't think it is right to use exceptions for flow control.
>
Why do not push this responsibility down to DAO layer wrapper?
I think that  my trick: CGLib proxy for DAO classes, would do exactly
what you are trying to accomplish, and will do that absolutely
transparently
http://kgionline.com/articles/aop_1/aop1.jsp
Another example of real use:
http://kgionline.com/xflow2/doc/xflow2/code_tricks.html

Ant by the way the same trick could be done with HiveMind - I tried and
it works.

--
Thanks,

Konstantin Ignatyev

http://www.kgionline.com





PS: If this is a typical day on planet earth, humans will add fifteen million tons of carbon to the atmosphere, destroy 115 square miles of tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2.700 tons of CFCs to the stratosphere, and increase their population by 263.000

Bowers, C.A.  The Culture of Denial:  
Why the Environmental Movement Needs a Strategy for Reforming Universities and Public Schools.  
New York:  State University of New York Press, 1997: (4) (5) (p.206)


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Erik Hatcher

On May 11, 2005, at 9:46 AM, Konstantin Iignatyev wrote:

> Erik Hatcher wrote:
>
>
>>
>> My most recent struggle is with integrating auto-commit (via  
>> Cayenne)  for all of my listener methods without them having to  
>> explicitly have  a Cayenne dependence and mandating that they  
>> individually call the  Cayenne commit API.  IM'ing with Howard a  
>> bit, he gave me some tips  on how to hook listener methods.  I  
>> opted for the simplest one, by  overriding getListeners() and  
>> creating custom IActionListener's  around the ones provided by  
>> Tapestry itself.  This worked great,  until I hit a page that  
>> throws a RedirectException.  So now I have to  code in the  
>> catching of (Page)RedirectException and re-throw it.  I  don't  
>> think it is right to use exceptions for flow control.
>>
>>
> Why do not push this responsibility down to DAO layer wrapper?

My "DAO" layer is Cayenne, and I'm accessing my persistent business  
objects directly from my Tapestry listener methods.  These business  
objects have methods, and aren't just data holders.

I want the transaction to either commit or rollback after a listener  
method is done.

> I think that  my trick: CGLib proxy for DAO classes, would do  
> exactly what you are trying to accomplish, and will do that  
> absolutely transparently
> http://kgionline.com/articles/aop_1/aop1.jsp
> Another example of real use: http://kgionline.com/xflow2/doc/xflow2/ 
> code_tricks.html

I don't see how it'd be transparent.  What is more transparent than a  
listener that doesn't have any explicit commits or rollbacks in it?  
In fact, my Tapestry code will have no direct use of Cayenne's API if  
all goes as planned.

> Ant by the way the same trick could be done with HiveMind - I tried  
> and it works.

There is not a way to intercept listener method invocations with  
HiveMind that I know of.  If you know of a way, could you please share?

Thanks,
     Erik


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Konstantin Ignatyev
Erik Hatcher wrote:

>
> I don't see how it'd be transparent.  What is more transparent than a  
> listener that doesn't have any explicit commits or rollbacks in it?  
> In fact, my Tapestry code will have no direct use of Cayenne's API if  
> all goes as planned.
>
IMO a proxy wrapped POJO is more transparent because it works properly
no matter who and why calls its methods. My trick works with the assumption
that  transactions starts when a thread enters first DAO layer method
and finishes when the thread leaves it. It also correctly propagates the
same transaction to all others call of DAO layer if necessary.

So, I do not know details of your implementation, but generally speaking
if your object has business methods and they invoke DAO layer, then my
trick works just fine.

>> Ant by the way the same trick could be done with HiveMind - I tried  
>> and it works.
>
>
> There is not a way to intercept listener method invocations with  
> HiveMind that I know of.  If you know of a way, could you please share?
>
The trick is to intercept invocations of all or selected methods on
certain DAO objects (singletons) no matter who invokes them.
That is just a matter of using proper HM interceptor, pretty much like
the one I have used to compare performance of AOP
http://kgionline.com/articles/aop_1/aop_perf.jsp , scroll down to HM case.


Let me repeat one more time - the trick completely decouples DAO from
all its users (UI, batch, WS, etc).
Actually all those DAOs become equivalents of Stateless Session Beans
where every method is transactional.

That may or may not work for you, but I certainly discourage explicit
transaction management in UI.

--
Thanks,

Konstantin Ignatyev

http://www.kgionline.com





PS: If this is a typical day on planet earth, humans will add fifteen million tons of carbon to the atmosphere, destroy 115 square miles of tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2.700 tons of CFCs to the stratosphere, and increase their population by 263.000

Bowers, C.A.  The Culture of Denial:  
Why the Environmental Movement Needs a Strategy for Reforming Universities and Public Schools.  
New York:  State University of New York Press, 1997: (4) (5) (p.206)


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Erik Hatcher

On May 11, 2005, at 12:09 PM, Konstantin Iignatyev wrote:

> Erik Hatcher wrote:
>
>
>>
>> I don't see how it'd be transparent.  What is more transparent  
>> than a  listener that doesn't have any explicit commits or  
>> rollbacks in it? In fact, my Tapestry code will have no direct use  
>> of Cayenne's API if  all goes as planned.
>>
>>
> IMO a proxy wrapped POJO is more transparent because it works  
> properly no matter who and why calls its methods. My trick works  
> with the assumption
> that  transactions starts when a thread enters first DAO layer  
> method and finishes when the thread leaves it. It also correctly  
> propagates the same transaction to all others call of DAO layer if  
> necessary.
>
> So, I do not know details of your implementation, but generally  
> speaking if your object has business methods and they invoke DAO  
> layer, then my trick works just fine.

For the sake of discussion, view the Tapestry listener method as the  
DAO layer method.  I want to wrap a transaction around that.

The question is, how can you wrap this transaction boundary around  
Tapestry listener invocations?

>> There is not a way to intercept listener method invocations with  
>> HiveMind that I know of.  If you know of a way, could you please  
>> share?
>>
>>
> The trick is to intercept invocations of all or selected methods on  
> certain DAO objects (singletons) no matter who invokes them.
> That is just a matter of using proper HM interceptor, pretty much  
> like the one I have used to compare performance of AOP
> http://kgionline.com/articles/aop_1/aop_perf.jsp , scroll down to  
> HM case.
>
>
> Let me repeat one more time - the trick completely decouples DAO  
> from all its users (UI, batch, WS, etc).
> Actually all those DAOs become equivalents of Stateless Session  
> Beans where every method is transactional.

And every method invocation is followed by a commit?  I want to be a  
bit less fine grained than that, and make several business method  
calls possibly before a commit occurs.  I assume that is what you do  
with yours, I'm just not clear on that based on what you just said.

> That may or may not work for you, but I certainly discourage  
> explicit transaction management in UI.

I'm definitely working to avoid explicit transaction management, that  
is the crux of my issue here.

My disclaimer is that I've historically avoided the database tier as  
others have been much more skilled and actually enjoyed it more than  
I do - so I'm learning this stuff now because I'm a one-man team on  
my current project.

     Erik


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Konstantin Ignatyev
 >For the sake of discussion, view the Tapestry listener method as the  
DAO layer method.  I want to wrap a transaction around that.
 >The question is, how can you wrap this transaction boundary around  
Tapestry listener invocations?

Lets assume:
- we have two DAO classes UserDAO and AddressDAO;
- listener method is updateUser( User, Address) method on UserDAO;

1. the trick employs factory pattern, that means that some object
(HiveMind, or CGLib enhancer factory ) has a method
getSingleton( Class clazz );

2. on a page we would have a field like this:
UserDAO udao = (UserDAO ) factory.getSingleton( UserDAO.class);

udao will NOT be instance of UserDAO class but its subclass (in case of
CGLib) or wrapped interface implementation in case of HM;

3. Factory makes sure that every method of original DAO classes is
wrapped in transaction and exception handling logic;

4. At runtime method udao.updateUser( User, Address) will call
AddressDAO like this
updateUser( User, Address){
   ...
   AddressDAO adao = (AddressDAO) factory.getSingleton( AddressDAO.class);
   adao.updateAddress( a );
}

 updateAddress( a )  will work within the current transaction because
enhanced logic sees it in ThreadLocal environment, as the other DAO classes.
So, we can invoke multiple methods before transaction commit or rollback.

Note, if we will call adao.updateAddress( a ) directly from another
listener method, then this method WILL start transaction and then finish
it properly.
That is what I call transparent and non-obtrusive


You seem to be too Tapestry focused, try imagine that there is no
T(yet), but just a bunch of JUnit test cases:
my approach is very JUnit friendly - it works just fine and provides
same Transactional context for those bare JUnit tests.
It allows convenient and fast code-compile-test cycles.


Hope it is clearer now.

Erik Hatcher wrote:

> On May 11, 2005, at 12:09 PM, Konstantin Iignatyev wrote:
>
>> Erik Hatcher wrote:
>>
>>
>>>
>>> I don't see how it'd be transparent.  What is more transparent  than
>>> a  listener that doesn't have any explicit commits or  rollbacks in
>>> it? In fact, my Tapestry code will have no direct use  of Cayenne's
>>> API if  all goes as planned.
>>>
>>>
>> IMO a proxy wrapped POJO is more transparent because it works  
>> properly no matter who and why calls its methods. My trick works  
>> with the assumption
>> that  transactions starts when a thread enters first DAO layer  
>> method and finishes when the thread leaves it. It also correctly  
>> propagates the same transaction to all others call of DAO layer if  
>> necessary.
>>
>> So, I do not know details of your implementation, but generally  
>> speaking if your object has business methods and they invoke DAO  
>> layer, then my trick works just fine.
>
>
> For the sake of discussion, view the Tapestry listener method as the  
> DAO layer method.  I want to wrap a transaction around that.
>
> The question is, how can you wrap this transaction boundary around  
> Tapestry listener invocations?
>
>>> There is not a way to intercept listener method invocations with  
>>> HiveMind that I know of.  If you know of a way, could you please  
>>> share?
>>>
>>>
>> The trick is to intercept invocations of all or selected methods on  
>> certain DAO objects (singletons) no matter who invokes them.
>> That is just a matter of using proper HM interceptor, pretty much  
>> like the one I have used to compare performance of AOP
>> http://kgionline.com/articles/aop_1/aop_perf.jsp , scroll down to  HM
>> case.
>>
>>
>> Let me repeat one more time - the trick completely decouples DAO  
>> from all its users (UI, batch, WS, etc).
>> Actually all those DAOs become equivalents of Stateless Session  
>> Beans where every method is transactional.
>
>
> And every method invocation is followed by a commit?  I want to be a  
> bit less fine grained than that, and make several business method  
> calls possibly before a commit occurs.  I assume that is what you do  
> with yours, I'm just not clear on that based on what you just said.
>
>> That may or may not work for you, but I certainly discourage  
>> explicit transaction management in UI.
>
>
> I'm definitely working to avoid explicit transaction management, that  
> is the crux of my issue here.
>
> My disclaimer is that I've historically avoided the database tier as  
> others have been much more skilled and actually enjoyed it more than  
> I do - so I'm learning this stuff now because I'm a one-man team on  
> my current project.
>
>     Erik
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
Thanks,

Konstantin Ignatyev

http://www.kgionline.com





PS: If this is a typical day on planet earth, humans will add fifteen million tons of carbon to the atmosphere, destroy 115 square miles of tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2.700 tons of CFCs to the stratosphere, and increase their population by 263.000

Bowers, C.A.  The Culture of Denial:  
Why the Environmental Movement Needs a Strategy for Reforming Universities and Public Schools.  
New York:  State University of New York Press, 1997: (4) (5) (p.206)


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

IRequestCycle cookie madness

Eric Schneider
Hi,

I'm having trouble getting my head around some behavior that I'm  
seeing.   Here's the scenario:

I have two components that appear on every page of my application,  
component A & B.

When I start a new Visit to the application, the Home page renders  
and users can invoke an action on component A that sets a cookie and  
returns the next page.   Based on the value of this cookie some  
behavior on component B should change when the next page is  
rendered.   Simple enough.

The problem I'm having, for whatever reason, component B is not able  
to retrieve the cookie value on the first render after the cookie is  
originally set.   All subsequent actions (any action, not just the  
one related to Component A), component B is able to retrieve the  
cookie successfully.

Here's where I get lost trying to figure out how the RequestCycle  
works.  Both components (A & B) implement PageRenderListener and  
define a pageBeginRender(PageEvent event) method (this is where I  
attempt get a handle of the cookie).  I've added some debugging  
output to these methods and the results are a bit puzzling.

After first action is invoked, the order goes something like this:

- Component A: pageBeginRender() is fired
- Component B: pageBeginRender() is fired
- Cookie is written
- Component A: pageBeginRender() is fired (2nd time)
- Component B: pageBeginRender() is fired (2nd time)
- Attempt to retrieve cookie returns null
- Component A: pageBeginRender() is fired (3rd time)
- Component B: pageBeginRender() is fired (3rd time)
- Additional attempt to retrieve cookie returns null
- Next page renders.

The any additional request, the cycle's path seems much simpler:

- Component A: pageBeginRender() is fired
- Component B: pageBeginRender() is fired
- Cookie successfully returns

Anyone have any advice on what's going on here?

Thanks,
Eric




---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: IRequestCycle cookie madness

Barry Books
From the way you describe your code you are trying to retrieve the cookie in the same request cycle you set it. The problem is setting the cookie just puts the cookie into the response header. Until the browser makes another request the cookie is not really set. You could either hide this feature by also storing the information in the visit object or throw a page redirect exception which would cause the browser to retrieve a new page with the cookie set.

Barry
 
On Wednesday, May 11, 2005, at 01:46PM, Eric Schneider <[hidden email]> wrote:

>Hi,
>
>I'm having trouble getting my head around some behavior that I'm  
>seeing.   Here's the scenario:
>
>I have two components that appear on every page of my application,  
>component A & B.
>
>When I start a new Visit to the application, the Home page renders  
>and users can invoke an action on component A that sets a cookie and  
>returns the next page.   Based on the value of this cookie some  
>behavior on component B should change when the next page is  
>rendered.   Simple enough.
>
>The problem I'm having, for whatever reason, component B is not able  
>to retrieve the cookie value on the first render after the cookie is  
>originally set.   All subsequent actions (any action, not just the  
>one related to Component A), component B is able to retrieve the  
>cookie successfully.
>
>Here's where I get lost trying to figure out how the RequestCycle  
>works.  Both components (A & B) implement PageRenderListener and  
>define a pageBeginRender(PageEvent event) method (this is where I  
>attempt get a handle of the cookie).  I've added some debugging  
>output to these methods and the results are a bit puzzling.
>
>After first action is invoked, the order goes something like this:
>
>- Component A: pageBeginRender() is fired
>- Component B: pageBeginRender() is fired
>- Cookie is written
>- Component A: pageBeginRender() is fired (2nd time)
>- Component B: pageBeginRender() is fired (2nd time)
>- Attempt to retrieve cookie returns null
>- Component A: pageBeginRender() is fired (3rd time)
>- Component B: pageBeginRender() is fired (3rd time)
>- Additional attempt to retrieve cookie returns null
>- Next page renders.
>
>The any additional request, the cycle's path seems much simpler:
>
>- Component A: pageBeginRender() is fired
>- Component B: pageBeginRender() is fired
>- Cookie successfully returns
>
>Anyone have any advice on what's going on here?
>
>Thanks,
>Eric
>
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: [hidden email]
>For additional commands, e-mail: [hidden email]
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: IRequestCycle cookie madness

Eric Schneider
Barry,

>> The problem is setting the cookie just puts the cookie into the  
>> response header. Until the browser makes another request the  
>> cookie is not really set.

Is this really the case?  If you set a cookie in a http request, it's  
not available in the http response?   Because I can confirm that the  
cookie was set in the browser when the response comes back (addition  
request doesn't seem to be required).

I'll try the RedirectException, see if that does the trick.

Thanks for the suggestion.

e.


On May 11, 2005, at 3:01 PM, Barry Books wrote:

>> From the way you describe your code you are trying to retrieve the  
>> cookie in the same request cycle you set it. The problem is  
>> setting the cookie just puts the cookie into the response header.  
>> Until the browser makes another request the cookie is not really  
>> set. You could either hide this feature by also storing the  
>> information in the visit object or throw a page redirect exception  
>> which would cause the browser to retrieve a new page with the  
>> cookie set.
>>
>
> Barry
>
> On Wednesday, May 11, 2005, at 01:46PM, Eric Schneider  
> <[hidden email]> wrote:
>
>
>> Hi,
>>
>> I'm having trouble getting my head around some behavior that I'm
>> seeing.   Here's the scenario:
>>
>> I have two components that appear on every page of my application,
>> component A & B.
>>
>> When I start a new Visit to the application, the Home page renders
>> and users can invoke an action on component A that sets a cookie and
>> returns the next page.   Based on the value of this cookie some
>> behavior on component B should change when the next page is
>> rendered.   Simple enough.
>>
>> The problem I'm having, for whatever reason, component B is not able
>> to retrieve the cookie value on the first render after the cookie is
>> originally set.   All subsequent actions (any action, not just the
>> one related to Component A), component B is able to retrieve the
>> cookie successfully.
>>
>> Here's where I get lost trying to figure out how the RequestCycle
>> works.  Both components (A & B) implement PageRenderListener and
>> define a pageBeginRender(PageEvent event) method (this is where I
>> attempt get a handle of the cookie).  I've added some debugging
>> output to these methods and the results are a bit puzzling.
>>
>> After first action is invoked, the order goes something like this:
>>
>> - Component A: pageBeginRender() is fired
>> - Component B: pageBeginRender() is fired
>> - Cookie is written
>> - Component A: pageBeginRender() is fired (2nd time)
>> - Component B: pageBeginRender() is fired (2nd time)
>> - Attempt to retrieve cookie returns null
>> - Component A: pageBeginRender() is fired (3rd time)
>> - Component B: pageBeginRender() is fired (3rd time)
>> - Additional attempt to retrieve cookie returns null
>> - Next page renders.
>>
>> The any additional request, the cycle's path seems much simpler:
>>
>> - Component A: pageBeginRender() is fired
>> - Component B: pageBeginRender() is fired
>> - Cookie successfully returns
>>
>> Anyone have any advice on what's going on here?
>>
>> Thanks,
>> Eric
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: tapestry-user-
>> [hidden email]
>>
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


Reply | Threaded
Open this post in threaded view
|

Re: IRequestCycle cookie madness

Barry Books
 I'm pretty sure that's the case. Perhaps the best way to think of it is setCookie puts a cookie into the response header and getCookie gets one from the request header.


On Wednesday, May 11, 2005, at 02:27PM, Eric Schneider <[hidden email]> wrote:

>Barry,
>
>>> The problem is setting the cookie just puts the cookie into the  
>>> response header. Until the browser makes another request the  
>>> cookie is not really set.
>
>Is this really the case?  If you set a cookie in a http request, it's  
>not available in the http response?   Because I can confirm that the  
>cookie was set in the browser when the response comes back (addition  
>request doesn't seem to be required).
>
>I'll try the RedirectException, see if that does the trick.
>
>Thanks for the suggestion.
>
>e.
>
>
>On May 11, 2005, at 3:01 PM, Barry Books wrote:
>
>>> From the way you describe your code you are trying to retrieve the  
>>> cookie in the same request cycle you set it. The problem is  
>>> setting the cookie just puts the cookie into the response header.  
>>> Until the browser makes another request the cookie is not really  
>>> set. You could either hide this feature by also storing the  
>>> information in the visit object or throw a page redirect exception  
>>> which would cause the browser to retrieve a new page with the  
>>> cookie set.
>>>
>>
>> Barry
>>
>> On Wednesday, May 11, 2005, at 01:46PM, Eric Schneider  
>> <[hidden email]> wrote:
>>
>>
>>> Hi,
>>>
>>> I'm having trouble getting my head around some behavior that I'm
>>> seeing.   Here's the scenario:
>>>
>>> I have two components that appear on every page of my application,
>>> component A & B.
>>>
>>> When I start a new Visit to the application, the Home page renders
>>> and users can invoke an action on component A that sets a cookie and
>>> returns the next page.   Based on the value of this cookie some
>>> behavior on component B should change when the next page is
>>> rendered.   Simple enough.
>>>
>>> The problem I'm having, for whatever reason, component B is not able
>>> to retrieve the cookie value on the first render after the cookie is
>>> originally set.   All subsequent actions (any action, not just the
>>> one related to Component A), component B is able to retrieve the
>>> cookie successfully.
>>>
>>> Here's where I get lost trying to figure out how the RequestCycle
>>> works.  Both components (A & B) implement PageRenderListener and
>>> define a pageBeginRender(PageEvent event) method (this is where I
>>> attempt get a handle of the cookie).  I've added some debugging
>>> output to these methods and the results are a bit puzzling.
>>>
>>> After first action is invoked, the order goes something like this:
>>>
>>> - Component A: pageBeginRender() is fired
>>> - Component B: pageBeginRender() is fired
>>> - Cookie is written
>>> - Component A: pageBeginRender() is fired (2nd time)
>>> - Component B: pageBeginRender() is fired (2nd time)
>>> - Attempt to retrieve cookie returns null
>>> - Component A: pageBeginRender() is fired (3rd time)
>>> - Component B: pageBeginRender() is fired (3rd time)
>>> - Additional attempt to retrieve cookie returns null
>>> - Next page renders.
>>>
>>> The any additional request, the cycle's path seems much simpler:
>>>
>>> - Component A: pageBeginRender() is fired
>>> - Component B: pageBeginRender() is fired
>>> - Cookie successfully returns
>>>
>>> Anyone have any advice on what's going on here?
>>>
>>> Thanks,
>>> Eric
>>>
>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: tapestry-user-
>>> [hidden email]
>>>
>>>
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Ben Eng
In reply to this post by Erik Hatcher
On Wed, May 11, 2005 at 11:36:39AM -0400, Erik Hatcher wrote:
>
> There is not a way to intercept listener method invocations with  
> HiveMind that I know of.  If you know of a way, could you please share?

You don't like how I implemented events before and after listener
invocation?

  http://issues.apache.org/jira/browse/TAPESTRY-294

Ben

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Erik Hatcher

On May 11, 2005, at 5:02 PM, Ben Eng wrote:

> On Wed, May 11, 2005 at 11:36:39AM -0400, Erik Hatcher wrote:
>
>>
>> There is not a way to intercept listener method invocations with
>> HiveMind that I know of.  If you know of a way, could you please  
>> share?
>>
>
> You don't like how I implemented events before and after listener
> invocation?
>
>   http://issues.apache.org/jira/browse/TAPESTRY-294

To be honest, I had forgotten about your patch.

Despite being a Tapestry committer, I typically try to solve problems  
without modification to the underlying frameworks (although I have  
usually ended up under the hood of most of the libraries I use).  
I've pasted, below, the hack I've used.

I would prefer if Howard signed off on your approach.  I would think  
a more HiveMind-esque technique would be more to the Tapestry 4.0  
style.  I have no objections to what you've done.  Though I'm not  
sure I'd be able to do what I've done with it, considering the way  
Page/RedirectException are handled.  In your terms my post-listener  
event is fired only if the original listener succeed without thrown  
an exception or if throws Page/RedirectException.  I don't think an  
"after" listener event could be coded in your contribution to do  
that.  Please correct me if I'm wrong.

Throwing of an exception for flow control is something we should  
probably re-architect though.

     Erik


   public ListenerMap getListeners() {
     final ListenerMap orig =  super.getListeners();
     return new ListenerMap() {

       public IActionListener getListener(String name) {
         final IActionListener origListener = orig.getListener(name);
         return new IActionListener() {

           public void actionTriggered(IComponent component,  
IRequestCycle cycle) {
             RuntimeException e = null;
             try {
               origListener.actionTriggered(component, cycle);
             }
             catch (RedirectException re) {
               e = re;
             }
             catch (PageRedirectException pre) {
               e = pre;
             }

             // only Tapestry's two flow control "exceptions" make it  
this far, and then are rethrown
             getDataContext().commitChanges();

             if (e != null) throw e;
           }

         };
       }

       public Collection getListenerNames() {
         return orig.getListenerNames();
       }

       public boolean canProvideListener(String name) {
         return orig.canProvideListener(name);
       }
     };
   }

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Vjeran Marcinko
In reply to this post by Erik Hatcher
----- Original Message -----
From: "Erik Hatcher" <[hidden email]>
To: "Tapestry users" <[hidden email]>
Sent: Wednesday, May 11, 2005 2:43 PM
Subject: Re: Tapestry's Simplicity Blues


> I enjoy your posts and this one was no exception.  You provide a much
> needed refreshing viewpoint on Tapestry.  I converse with Howard
> about complexity on a regular basis.  I won't paraphrase his view,
> but it does contrast with mine.  I feel that complexity leaks, much
> like the age old "abstractions leak" mantra.  The more complex the
> core of Tapestry, the more magic that it contains, the more likely
> that complexity is felt by the programmer trying to build a page.

Yes Erik,
More magic means more complexity.
Sometimes, it gives me thoughts that it's not Tapestry itself the reason for
complexity. Sure, probably bunch of things can be better, and some of them
become in new versions. But maybe it's just this whole event-driven
component aproach that is sooo different from stateless HTTP world, that it
requires from framework to do a lot of magic, inevitably leading to
complexity.
Maybe I'm wrong, but it seems to me that request-driven frameworks (Spring
MVC, Turbine, WebWork...) are much simplier to develop. I'm not talking
about benefits that users have, just from framework developer's viewpoint.

Thing is that I never worked with JSF or APS.NET to judge Tapestry with
other component web frameworks. From what I've read around, I sincerely
doubt that JSF is simplier, but I would really like some expeienced ASP.NET
developer to say his opinion.

Comparing component web frameworks and request-driven ones, somehow remind
me of statement I heard once about VB and Java :
"Newbies in VB can develop only crappy software. Newbies in Java can't do
anything."

Hope Howard will not take this thread as attack on his framework. I wouldn't
be using it if I thought it was something better out there.

-Vjeran



--
No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.308 / Virus Database: 266.11.8 - Release Date: 10.5.2005


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: Tapestry's Simplicity Blues

Patrick Casey
<snip>
> Thing is that I never worked with JSF or APS.NET to judge Tapestry with
> other component web frameworks. From what I've read around, I sincerely
> doubt that JSF is simplier, but I would really like some expeienced
> ASP.NET
> developer to say his opinion.

I wouldn't necessarily call myself a .NET expert, but I did prototype a
system in in a few months ago (I decided not to go down that road so I'm
back in java). The short version of my experience.

.NET does make the simple stuff simple. If you want to build a quick and
dirty CRUD app with only a few forms, .NET is way faster than anything I've
yet found in the java world. Between the WYSIWIG form editor, the component
library, and the magic "don't worry about it, it just works" persistence
strategy they have, it's really easy to do easy stuff.

But, and here's where .NET and I parted ways, it doesn't have a lot of
features to make the *hard* stuff simple. Want an abstract object
persistence layer like Hibernate? So sorry, roll your own, or use a thin
resultset wrapper like ADO. Want to use lots of generic forms and runtime
data binding? Sorry, it's a design time framework. Sure you *can* bind at
runtime, but if you do you can't use any of the cool features that made the
easy stuff easy.

All in all, I felt like it was something of a trap for serious development
work. It makes banging together a sketchy prototype really easy, but then
you end up not being able to use any of those easy features on the real
project.

If somebody would marry the easy-stuff-is-easy part of .NET with the
hard-stuff-is-possible part of hibernate/java/tapestry, I'd switch to it in
a heartbeat. To date though, nobody has pulled it off. If I were a gambling
man, I'd bet on the Eclipse group making a decent go at it in the next
couple of years.

I'm not all that confident though that the current stable of open source
projects out there (choose your poison) are going to get there though. In my
experience they're usually written by developers who got fed up with crap
like .NET and decided to tackle the interesting "hard stuff" problems
instead of the tedious "easy stuff" issues. So we have at least a half dozen
web application frameworks out there, but nobody has yet written a decent
WYSYWIG gui for any of them (if I'm wrong here I'm 100% certain I'll get 20
emails about it :).

In any event, the short version is Tapestry/Hibernate/Java is way more
*powerful* than .NET for the kind of work I do. It's not, however, easier.

--- Pat



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: Tapestry's Simplicity Blues

Markus Eberle
Zitat von Patrick Casey <[hidden email]>:

[...]
> But, and here's where .NET and I parted ways, it doesn't have a lot of
> features to make the *hard* stuff simple. Want an abstract object
> persistence layer like Hibernate? So sorry, roll your own, or use a thin
> resultset wrapper like ADO. Want to use lots of generic forms and runtime
> data binding? Sorry, it's a design time framework. Sure you *can* bind at
> runtime, but if you do you can't use any of the cool features that made the
> easy stuff easy.
[...]

I have not done much things using .Net, but there is NHibernate for .Net which
is a "port" of hibernate to .Net. even the Spring framework is ported :-)

But the WYSIWYG feature is quite cool.

So back to tapestry :-)

Cheers,
    Markus

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Bryan Lewis
In reply to this post by Patrick Casey
These comments made sense.  The open-source community does spend relatively
little of its resources on the tedious make-it-easy issues.  (With Firefox
being a good counter-example... how did that project manage it?)

> If somebody would marry the easy-stuff-is-easy part of .NET with the
> hard-stuff-is-possible part of hibernate/java/tapestry....

A great example of this was the old WebObjects Direct-To-Web framework.  You
could throw together a quick CRUD app in no time... point the tool at your
model and hit a button.  It took me less than a minute to get a running app
the first time I tried it (four years ago).  You could revise the pages
inside the wizard-ish GUI builder tool, but when you were ready to make more
serious modifications you could tell it to generate the source code.  (I
think they called it "freezing" the app.)  It would give you a fully
functional app built on the normal frameworks and you could do whatever you
want (except go back into the wizard-ish GUI builder tool).

Here's a description I found with a quick google.
http://developer.apple.com/documentation/LegacyTechnologies/WebObjects/WebObjects_5.1/DirectToWeb/WalkThrough/Generating_Components.html

"WebAssistant" is what they call the wizard-ish GUI builder now.  A
WebAssistant on top of Tapestry would be awesome.


----- Original Message -----
From: "Patrick Casey" <[hidden email]>
To: "'Tapestry users'" <[hidden email]>
Sent: Thursday, May 12, 2005 3:02 AM
Subject: RE: Tapestry's Simplicity Blues


> <snip>
> > Thing is that I never worked with JSF or APS.NET to judge Tapestry with
> > other component web frameworks. From what I've read around, I sincerely
> > doubt that JSF is simplier, but I would really like some expeienced
> > ASP.NET
> > developer to say his opinion.
>
> I wouldn't necessarily call myself a .NET expert, but I did prototype a
> system in in a few months ago (I decided not to go down that road so I'm
> back in java). The short version of my experience.
>
> .NET does make the simple stuff simple. If you want to build a quick and
> dirty CRUD app with only a few forms, .NET is way faster than anything
I've
> yet found in the java world. Between the WYSIWIG form editor, the
component
> library, and the magic "don't worry about it, it just works" persistence
> strategy they have, it's really easy to do easy stuff.
>
> But, and here's where .NET and I parted ways, it doesn't have a lot of
> features to make the *hard* stuff simple. Want an abstract object
> persistence layer like Hibernate? So sorry, roll your own, or use a thin
> resultset wrapper like ADO. Want to use lots of generic forms and runtime
> data binding? Sorry, it's a design time framework. Sure you *can* bind at
> runtime, but if you do you can't use any of the cool features that made
the
> easy stuff easy.
>
> All in all, I felt like it was something of a trap for serious development
> work. It makes banging together a sketchy prototype really easy, but then
> you end up not being able to use any of those easy features on the real
> project.
>
> If somebody would marry the easy-stuff-is-easy part of .NET with the
> hard-stuff-is-possible part of hibernate/java/tapestry, I'd switch to it
in
> a heartbeat. To date though, nobody has pulled it off. If I were a
gambling
> man, I'd bet on the Eclipse group making a decent go at it in the next
> couple of years.
>
> I'm not all that confident though that the current stable of open source
> projects out there (choose your poison) are going to get there though. In
my
> experience they're usually written by developers who got fed up with crap
> like .NET and decided to tackle the interesting "hard stuff" problems
> instead of the tedious "easy stuff" issues. So we have at least a half
dozen
> web application frameworks out there, but nobody has yet written a decent
> WYSYWIG gui for any of them (if I'm wrong here I'm 100% certain I'll get
20

> emails about it :).
>
> In any event, the short version is Tapestry/Hibernate/Java is way more
> *powerful* than .NET for the kind of work I do. It's not, however, easier.
>
> --- Pat
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

RE: Tapestry's Simplicity Blues

Karthik Abram
In reply to this post by Patrick Casey

I've build fairly substantial applications with .NET - and I will have to
disagree with some of the points below. True, .NET doesn't have a Hibernate
like persistence layer, but the reality is that while java produced a
zillion persistence options for the "Enterprise" app, ADO.NET's simple
in-memory DataTable approach will suffice for 99% of the apps out there.
That said, .NET 2.0 will change quite a few things ...

The distinction between .NET and Tapestry is this: (a) State persistence in
the client using the view-state, (b) GUI design tool, components that have a
distince "design time" and "run time" mode of operation (components have an
interface that allow it to interact with VS .NET for design time
manipulation); (c) Thriving commercial component market with some really
slick components.

Of course the availability of tons of books/literature/websites also makes
the learning curve a lot easier. That said, Tapestry will run on Linux, .NET
requires a licensed OS.s

-----Original Message-----
From: Patrick Casey [mailto:[hidden email]]
Sent: Thursday, May 12, 2005 3:02 AM
To: 'Tapestry users'
Subject: RE: Tapestry's Simplicity Blues


<snip>
> Thing is that I never worked with JSF or APS.NET to judge Tapestry with
> other component web frameworks. From what I've read around, I sincerely
> doubt that JSF is simplier, but I would really like some expeienced
> ASP.NET
> developer to say his opinion.

I wouldn't necessarily call myself a .NET expert, but I did prototype a
system in in a few months ago (I decided not to go down that road so I'm
back in java). The short version of my experience.

.NET does make the simple stuff simple. If you want to build a quick and
dirty CRUD app with only a few forms, .NET is way faster than anything I've
yet found in the java world. Between the WYSIWIG form editor, the component
library, and the magic "don't worry about it, it just works" persistence
strategy they have, it's really easy to do easy stuff.

But, and here's where .NET and I parted ways, it doesn't have a lot of
features to make the *hard* stuff simple. Want an abstract object
persistence layer like Hibernate? So sorry, roll your own, or use a thin
resultset wrapper like ADO. Want to use lots of generic forms and runtime
data binding? Sorry, it's a design time framework. Sure you *can* bind at
runtime, but if you do you can't use any of the cool features that made the
easy stuff easy.

All in all, I felt like it was something of a trap for serious development
work. It makes banging together a sketchy prototype really easy, but then
you end up not being able to use any of those easy features on the real
project.

If somebody would marry the easy-stuff-is-easy part of .NET with the
hard-stuff-is-possible part of hibernate/java/tapestry, I'd switch to it in
a heartbeat. To date though, nobody has pulled it off. If I were a gambling
man, I'd bet on the Eclipse group making a decent go at it in the next
couple of years.

I'm not all that confident though that the current stable of open source
projects out there (choose your poison) are going to get there though. In my
experience they're usually written by developers who got fed up with crap
like .NET and decided to tackle the interesting "hard stuff" problems
instead of the tedious "easy stuff" issues. So we have at least a half dozen
web application frameworks out there, but nobody has yet written a decent
WYSYWIG gui for any of them (if I'm wrong here I'm 100% certain I'll get 20
emails about it :).

In any event, the short version is Tapestry/Hibernate/Java is way more
*powerful* than .NET for the kind of work I do. It's not, however, easier.

--- Pat



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Michael Henderson
In reply to this post by Bryan Lewis
Hi,

I've been thinking about Tapestry component suites packaged with  
functional service layer objects. Using Spindle and the Palette plugin  
in Eclipse I'd like to be able to see users drag components onto pages  
that are already tied to application business logic. it won't work for  
all cases but there are common features like login, authorization,  
account management, catalog, comments, and so  on which I believe could  
be packaged this way.

I found this link in my search:

http://opensource.atlassian.com/confluence/spring/display/DISC/ 
Componentizing+Spring+and+Hibernate+Development

in this case common persistent classes have been packaged into JAR  
files for reuse in multiple applications. Layer service objects on top  
of something like this, bind Tapestry components to the service objects  
and package them up.


Mike


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry's Simplicity Blues

Konstantin Ignatyev
In reply to this post by Bryan Lewis
Bryan Lewis wrote:

>A great example of this was the old WebObjects Direct-To-Web framework.  You
>could throw together a quick CRUD app in no time... point the tool at your
>model and hit a button.  It took me less than a minute to get a running app
>the first time I tried it (four years ago).  You could revise the pages
>inside the wizard-ish GUI builder tool, but when you were ready to make more
>serious modifications you could tell it to generate the source code.  (I
>think they called it "freezing" the app.)  It would give you a fully
>functional app built on the normal frameworks and you could do whatever you
>want (except go back into the wizard-ish GUI builder tool).
>
>  
>

Sounds pretty much similar to Trails, or MDA, or Middlegen.

Just an observation

--
Thanks,

Konstantin Ignatyev

http://www.kgionline.com





PS: If this is a typical day on planet earth, humans will add fifteen million tons of carbon to the atmosphere, destroy 115 square miles of tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2.700 tons of CFCs to the stratosphere, and increase their population by 263.000

Bowers, C.A.  The Culture of Denial:  
Why the Environmental Movement Needs a Strategy for Reforming Universities and Public Schools.  
New York:  State University of New York Press, 1997: (4) (5) (p.206)


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

12