You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Vjeran Marcinko <vj...@email.t-com.hr> on 2005/08/28 12:51:44 UTC

The hardest problem ever

Sorry for flashy subject, but last time this question went into void, so ... 
;)
And I'm pretty sure that any experienced Tapestry developer came upon this 
problem.

Let's say I have custom service that does somethig, let's say for example 
that it generates PDF. Meaning, this service calls some handler interface to 
fetch PDF document instance for rendering (similar as IChartProvider 
interface from Workbench that provides JChart instances). Something like:

public interface PdfHandler {
    public PdfDocument getPdfDocument();
}
Of course, on user (page) side, there is special PdfLink component that 
contains ServiceLink for calling this custom service.

It's all nice and easy, but problem is that my page that implements this 
interface (provides PdfDocument), is dependant upon some parameter that was 
paseed to it for rendering, but PDF generation is subsequent request and 
page doesn't have this parameter anymore.

Now, I see 2 solutions, from which none is satisfying:

1. Interface should be something like:
public interface PdfHandler {
    public PdfDocument getPdfDocument(IRequestCycle cycle);
}
thus I would be able to pass arbitrary parameters similar as DirectLink 
does, and fetch it from IRequestCycle afterwards.
It's a bit uglier interface and problem is that there's no good example as 
how to do it with ServiceLink...

2. I should make this needed parameter as "client" persisted page property, 
thus it would persist till this subsequent request when I need to provide 
PdfDocument. Interface stays clean using this aproach.
Problem with this second way is that I dunno how to do it when this 
parameter is let's say primary key of some entity that is looping inside 
some For component on this page?!

Is there some nice solution to this?

Regards,
Vjeran


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Davor Hrg <hr...@gmail.com>.
I have an blurry idea of an approach for handling transient documents 
generated in loop,
but covers narrow usage like graphs and images used immediatelly on a page.

I'm generating content in for loop, and part of the content is a graph,
which is generated based on the current state.

Idea is to have a component that calls the method that generates the graph
and persists the result(with expire time), gives it an unique id an 
generates 
<img with the link to the service that retreives the result in subsequent 
request later on 
from storage.

This approach has issues, but brings a more natural feeling while generating 
a page,
another problem is that it can be misleeading for those beginners who have 
trouble
understanding why onclick can not call something from server(aside AJAX and 
alike).


further on, this approach if usefull can then be broadened to use 
serializable objects
instead of real data(data would be generated when needed), reduce the 
storage cost, 
and make it possible to be used in an situation where the result is not 
shown immediatelly
like an graph, but later when clicked like an pdf document.

Davor Hrg

On 8/29/05, Vjeran Marcinko <vj...@email.t-com.hr> wrote:
> 
> ----- Original Message -----
> From: "Kent Tong" <ke...@cpttm.org.mo>
> To: <ta...@jakarta.apache.org>
> Sent: Monday, August 29, 2005 3:13 AM
> Subject: Re: The hardest problem ever
> 
> 
> > Vjeran Marcinko <vjeran.marcinko <at> email.t-com.hr<http://email.t-com.hr>> 
> writes:
> >
> >> It's all nice and easy, but problem is that my page that implements 
> this
> >> interface (provides PdfDocument), is dependant upon some parameter that
> >> was
> >> paseed to it for rendering, but PDF generation is subsequent request 
> and
> >> page doesn't have this parameter anymore.
> >
> > Your PdfLink component should take a parameter and pass it to
> > your service, which will in turn pass to the PdfHandler. This
> > will work even in a loop.
> 
> Meaning, anyone who is making such general purpose service/component 
> should
> take care to provide way to pass arbitrary number of parameters (such as
> DirectLink offers) in some XServiceLink, and offer IRequestCycle argument
> inside XServiceProvider interface, so one could fetch parameters by
> cycle.getListenerParameters() in it because providing can be dependant 
> upon
> various app-specific parameters ?
> 
> And, "client" persisted property that would get set during each loop turn,
> thus generating additional URL parameter to all DirectLinks inside loop
> would not function ? Because there's no detailed docs about For component,
> and about various client peristence strategies, I guess MindBridge would
> know this best.
> 
> -Vjeran
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> 
>

Re: The hardest problem ever

Posted by Paul Cantrell <ca...@pobox.com>.
I believe the code Mark gave works only if the parameters are what  
Tapestry calls "squeezable," meaning that they can be encoded as a  
string in the URL. If your parameters aren't serializable, or  
shouldn't be serialized, write a custom SqueezeAdaptor.

     http://www.google.com/search?q=tapestry+squeeze+adaptor

And I *still* think you need to study the source code for  
ExternalService. It will answer a lot of the questions you're asking,  
and get you thinking along the right lines.

Did you look at it yet?

Paul


On Aug 29, 2005, at 9:51 AM, Mark Alcocer Flores wrote:

> No, actually, I just gave you and example, inside the array of  
> parameters, you can pass any amount
> of parameters or an object of anykind. Try it with more parameters  
> and it will work.
>
> Mark.
>
>> No good. That means that your service is developed only for  
>> passing String reportId and Integer reportType arguments. I want  
>> it to be generic service, capable of passing all kinds of  
>> parameters, same as you can pass any kind/amount of argument to  
>> IActionListener in case of DirectLink.
>>
>> -Vjeran
>>
>> ----- Original Message ----- From: "Mark Alcocer Flores"  
>> <su...@yahoo.com>
>>> To: "Tapestry users" <ta...@jakarta.apache.org>
>>> Sent: Monday, August 29, 2005 4:16 PM
>>> Subject: Re: The hardest problem ever
>>>
>>>
>>> From what I have read and understand  I think you could do  
>>> something like this:
>>>
>>> Lets say you have a Foreach component and inside you have links  
>>> to an special service
>>>
>>> <tr jwcid="@Foreach" source="ognl: reports" value="ognl: report"  
>>> element="tr">
>>> <td><span jwcid="@Insert" value="ognl: report.id"> 12345 </span></ 
>>> td>
>>> <td><span jwcid="@Insert" value="ognl: report.name"> Special  
>>> Report </span></td>
>>> <td>
>>> <a jwcid="@ServiceLink" service="reportService" parameters='ognl:  
>>> {report.id, report.type}'> See
>>> Report
>>> </a>
>>> </td>
>>> </tr>
>>>
>>> this way you can send parameters to your service and in the  
>>> service you will get them by doing
>>> somthing like this:
>>>
>>> public void service(IEngineServiceView engine, IRequestCycle  
>>> cycle, ResponseOutputStream output)
>>> throws ServletException, IOException {
>>>   Object[] parameters = getParameters(cycle);
>>>   String reportId =  (Integer) parameters[0];
>>>   Integer reportType = (String) parameters[1];
>>>   // Your call to your PDF service
>>> }
>

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Vjeran Marcinko <vj...@email.t-com.hr>.
So, I end up with provider interface method that has argument like Object[] 
args in itself, or IRequestCycle argument instead where I could fetch array 
of parameters by getListenerParameters() ?

-Vjeran

----- Original Message ----- 
From: "Mark Alcocer Flores" <su...@yahoo.com>
To: "Tapestry users" <ta...@jakarta.apache.org>
Sent: Monday, August 29, 2005 4:51 PM
Subject: Re: The hardest problem ever


No, actually, I just gave you and example, inside the array of parameters, 
you can pass any amount
of parameters or an object of anykind. Try it with more parameters and it 
will work.

Mark.

The Greatest Thing You'll Ever Learn
It's Just To Love And Be Loved In Return


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org



-- 
No virus found in this incoming message.
Checked by AVG Anti-Virus.
Version: 7.0.344 / Virus Database: 267.10.15/82 - Release Date: 25.8.2005



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Mark Alcocer Flores <su...@yahoo.com>.
No, actually, I just gave you and example, inside the array of parameters, you can pass any amount
of parameters or an object of anykind. Try it with more parameters and it will work.

Mark.

The Greatest Thing You'll Ever Learn
It's Just To Love And Be Loved In Return


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Vjeran Marcinko <vj...@email.t-com.hr>.
No good. That means that your service is developed only for passing String 
reportId and Integer reportType arguments. I want it to be generic service, 
capable of passing all kinds of parameters, same as you can pass any 
kind/amount of argument to IActionListener in case of DirectLink.

-Vjeran

----- Original Message ----- 
From: "Mark Alcocer Flores" <su...@yahoo.com>
To: "Tapestry users" <ta...@jakarta.apache.org>
Sent: Monday, August 29, 2005 4:16 PM
Subject: Re: The hardest problem ever


>From what I have read and understand  I think you could do something like 
this:

Lets say you have a Foreach component and inside you have links to an 
special service

<tr jwcid="@Foreach" source="ognl: reports" value="ognl: report" 
element="tr">
<td><span jwcid="@Insert" value="ognl: report.id"> 12345 </span></td>
<td><span jwcid="@Insert" value="ognl: report.name"> Special Report 
</span></td>
<td>
<a jwcid="@ServiceLink" service="reportService" parameters='ognl: 
{report.id, report.type}'> See
Report
</a>
</td>
</tr>

this way you can send parameters to your service and in the service you will 
get them by doing
somthing like this:

public void service(IEngineServiceView engine, IRequestCycle cycle, 
ResponseOutputStream output)
throws ServletException, IOException {
   Object[] parameters = getParameters(cycle);
   String reportId =  (Integer) parameters[0];
   Integer reportType = (String) parameters[1];
   // Your call to your PDF service
}

You will still need to define your link.

I hope this helps you in someway.

Mark.


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Mark Alcocer Flores <su...@yahoo.com>.
>From what I have read and understand  I think you could do something like this:

Lets say you have a Foreach component and inside you have links to an special service

<tr jwcid="@Foreach" source="ognl: reports" value="ognl: report" element="tr">
<td><span jwcid="@Insert" value="ognl: report.id"> 12345 </span></td>
<td><span jwcid="@Insert" value="ognl: report.name"> Special Report </span></td>
<td>
<a jwcid="@ServiceLink" service="reportService" parameters='ognl: {report.id, report.type}'> See
Report
</a>
</td>
</tr>

this way you can send parameters to your service and in the service you will get them by doing
somthing like this:

public void service(IEngineServiceView engine, IRequestCycle cycle, ResponseOutputStream output)
throws ServletException, IOException {
   Object[] parameters = getParameters(cycle);
   String reportId =  (Integer) parameters[0];
   Integer reportType = (String) parameters[1];
   // Your call to your PDF service
}

You will still need to define your link.

I hope this helps you in someway.

Mark.

The Greatest Thing You'll Ever Learn
It's Just To Love And Be Loved In Return


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Vjeran Marcinko <vj...@email.t-com.hr>.
----- Original Message ----- 
From: "Kent Tong" <ke...@cpttm.org.mo>
To: <ta...@jakarta.apache.org>
Sent: Monday, August 29, 2005 12:07 PM
Subject: Re: The hardest problem ever


> Vjeran Marcinko <vjeran.marcinko <at> email.t-com.hr> writes:
>
>> From: "Kent Tong" <kent <at> cpttm.org.mo>
>> > Your PdfLink component should take a parameter and pass it to
>> > your service, which will in turn pass to the PdfHandler. This
>> > will work even in a loop.
>>
>> Meaning, anyone who is making such general purpose service/component 
>> should
>> take care to provide way to pass arbitrary number of parameters (such as
>> DirectLink offers) in some XServiceLink, and offer IRequestCycle argument
>> inside XServiceProvider interface, so one could fetch parameters by
>> cycle.getListenerParameters() in it because providing can be dependant 
>> upon
>> various app-specific parameters ?
>
> No. If your XXXServiceProvider should take a Foo object as a parameter,
> then your XXXService and XXXServiecLink should both take a Foo object
> as a parameter.

That's impossible in cases where I have to specifically call 
callback/provider interface, and pass it as such to XXXLink component.
For example, I use iText library for PDF generation, and for performance 
reasons, this library doesn't work with some "prepared" PDF content argument 
for generation, but offers some Document instance to you , which is actually 
wrapped, and already opened OutputStream, thus writing to OutputStream 
happens in same time when one fills specify it's content, for cases when 
working with large documents.

So, my provider interface looks like:
public interface ITextPdfHandler {
    public void writePdfContent(Document document);
}

and page that implements it :
public abstract class PdfTestPage extends MyBasePage implements 
ITextPdfHandler {
    public abstract long getPresidentId();

    public ITextPdfHandler getPdfHandler() {
        return this;
    }

    public void writePdfContent(Document document) {
        long presidentId = getPresidentId();
        President president = getPresidentDao().getPresident(presidentId);
        document.add(new Paragraph("You vote for: " + president + "!"));
    }
}

So, problem is that in subsequent request, this "presidentId" isn't 
available anymore. I cannot prepare this Document instance before, and pass 
it as parameter to XXXLink component (and XXXService). This Document 
instance is "opened" during XXXService request processing , and passed to 
handler (page) as such for filling.

If I had something like :
public interface ITextPdfHandler {
    public void writePdfContent(IRequestCycle cycle, Document document);
}
then I would be able to fetch presidentId from cycle, that was passed 
beforehand through PdfLink component, right?

-Vjeran


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Kent Tong <ke...@cpttm.org.mo>.
Vjeran Marcinko <vjeran.marcinko <at> email.t-com.hr> writes:

> From: "Kent Tong" <kent <at> cpttm.org.mo>
> > Your PdfLink component should take a parameter and pass it to
> > your service, which will in turn pass to the PdfHandler. This
> > will work even in a loop.
> 
> Meaning, anyone who is making such general purpose service/component should 
> take care to provide way to pass arbitrary number of parameters (such as 
> DirectLink offers) in some XServiceLink, and offer IRequestCycle argument 
> inside XServiceProvider interface, so one could fetch parameters by 
> cycle.getListenerParameters() in it because providing can be dependant upon 
> various app-specific parameters ?

No. If your XXXServiceProvider should take a Foo object as a parameter,
then your XXXService and XXXServiecLink should both take a Foo object 
as a parameter.

> And, "client" persisted property that would get set during each loop turn, 
> thus generating additional URL parameter to all DirectLinks inside loop 
> would not function ? 

I am not sure if I understand what you're saying. A client persistent
property will NOT be set in each loop execution. It will be set once
for the whole page (or component) after the page is loaded.

--
Author of e-book for learning Tapestry (www.agileskills2.org/EWDT)


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Vjeran Marcinko <vj...@email.t-com.hr>.
----- Original Message ----- 
From: "Kent Tong" <ke...@cpttm.org.mo>
To: <ta...@jakarta.apache.org>
Sent: Monday, August 29, 2005 3:13 AM
Subject: Re: The hardest problem ever


> Vjeran Marcinko <vjeran.marcinko <at> email.t-com.hr> writes:
>
>> It's all nice and easy, but problem is that my page that implements this
>> interface (provides PdfDocument), is dependant upon some parameter that 
>> was
>> paseed to it for rendering, but PDF generation is subsequent request and
>> page doesn't have this parameter anymore.
>
> Your PdfLink component should take a parameter and pass it to
> your service, which will in turn pass to the PdfHandler. This
> will work even in a loop.

Meaning, anyone who is making such general purpose service/component should 
take care to provide way to pass arbitrary number of parameters (such as 
DirectLink offers) in some XServiceLink, and offer IRequestCycle argument 
inside XServiceProvider interface, so one could fetch parameters by 
cycle.getListenerParameters() in it because providing can be dependant upon 
various app-specific parameters ?

And, "client" persisted property that would get set during each loop turn, 
thus generating additional URL parameter to all DirectLinks inside loop 
would not function ? Because there's no detailed docs about For component, 
and about various client peristence strategies, I guess MindBridge would 
know this best.

-Vjeran 


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Kent Tong <ke...@cpttm.org.mo>.
Vjeran Marcinko <vjeran.marcinko <at> email.t-com.hr> writes:

> It's all nice and easy, but problem is that my page that implements this 
> interface (provides PdfDocument), is dependant upon some parameter that was 
> paseed to it for rendering, but PDF generation is subsequent request and 
> page doesn't have this parameter anymore.

Your PdfLink component should take a parameter and pass it to
your service, which will in turn pass to the PdfHandler. This
will work even in a loop.

--
Author of e-book for learning Tapestry (www.agileskills2.org/EWDT)




---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: The hardest problem ever

Posted by Paul Cantrell <ca...@pobox.com>.
I think (1) is on the right track, and although I don't really know  
how to do this either, it looks like you should examine the source  
code for ExternalService (or DirectService if you like).

If you're in 4.0, the key lines are:

     private LinkFactory _linkFactory;
     ...
         Object[] parameters = _linkFactory.extractListenerParameters 
(cycle);
         cycle.setListenerParameters(parameters);
     ...

But read through the whole class -- it looks like what you need is  
there.

Cheers,

Paul


On Aug 28, 2005, at 5:51 AM, Vjeran Marcinko wrote:

> Sorry for flashy subject, but last time this question went into  
> void, so ... ;)
> And I'm pretty sure that any experienced Tapestry developer came  
> upon this problem.
>
> Let's say I have custom service that does somethig, let's say for  
> example that it generates PDF. Meaning, this service calls some  
> handler interface to fetch PDF document instance for rendering  
> (similar as IChartProvider interface from Workbench that provides  
> JChart instances). Something like:
>
> public interface PdfHandler {
>    public PdfDocument getPdfDocument();
> }
> Of course, on user (page) side, there is special PdfLink component  
> that contains ServiceLink for calling this custom service.
>
> It's all nice and easy, but problem is that my page that implements  
> this interface (provides PdfDocument), is dependant upon some  
> parameter that was paseed to it for rendering, but PDF generation  
> is subsequent request and page doesn't have this parameter anymore.
>
> Now, I see 2 solutions, from which none is satisfying:
>
> 1. Interface should be something like:
> public interface PdfHandler {
>    public PdfDocument getPdfDocument(IRequestCycle cycle);
> }
> thus I would be able to pass arbitrary parameters similar as  
> DirectLink does, and fetch it from IRequestCycle afterwards.
> It's a bit uglier interface and problem is that there's no good  
> example as how to do it with ServiceLink...
>
> 2. I should make this needed parameter as "client" persisted page  
> property, thus it would persist till this subsequent request when I  
> need to provide PdfDocument. Interface stays clean using this aproach.
> Problem with this second way is that I dunno how to do it when this  
> parameter is let's say primary key of some entity that is looping  
> inside some For component on this page?!
>
> Is there some nice solution to this?
>
> Regards,
> Vjeran
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org