Hi Тимур,
Have you tried putting your asynchronous in pageAttached() methods (also
see @PageAttached annotation) in your components?

https://tapestry.apache.org/page-life-cycle.html

However pageAttached is invoked on all pages that are somehow involved in
the request processing (e.g. they are referenced via PageLink component)
and also for requests which are not rendered, so you would need some extra
checks to prevent unintended remote service calls.

PageAttached is deprecated in Tapestry 5.3, but it seems to be back and
working in 5.4.

http://tapestry.apache.org/5.3/apidocs/org/apache/tapestry5/annotations/PageAttached.html
http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/annotations/PageAttached.html


Another option is to use Heartbeat environmental service /
@HeartbeatDeferred annotation. In this case the component during normal
rendering just prepares some static template as Tapestry DOM, and invokes
asynchronous remote call, then on deferred call update the template with
actual content.


Best regards,
Cezary


On Tue, Apr 14, 2015 at 4:08 PM, Тимур Бухараев <bukhar...@gmail.com> wrote:

> I don't know how to solve my problem with Future. If you know, explain
> please.
>
> ProgressiveDisplay is a solution, but has some disadvantages.
>
> Now about moving data fetch logic.
>
> The problem is components are independent. Page class doesn't know about
> Component classes, component classes don't know about page and other
> components. They just embedded in a single tml document. So designer could
> move component to other place, and it still works. Each component fetches
> his own remote data independently. I can cache this data in service, if
> some components need same data, so the second component get cached data.
> But component is the only place who knows, what data it needs. For example,
> component displaying user profile. It needs user profile data, and it
> fetches it. So component is the only thing who knows it need profile data.
> But i can embed it in any tml in any place.
>
> On Tue, Apr 14, 2015 at 4:27 PM, Thiago H de Paula Figueiredo <
> thiag...@gmail.com> wrote:
>
> > On Tue, 14 Apr 2015 09:22:36 -0300, Тимур Бухараев <bukhar...@gmail.com>
> > wrote:
> >
> >  sorry, some mistake in sequence
> >>
> >> it should be:
> >> component1.setupRender();
> >> other component1 rendering
> >> component2.setupRender();
> >> other component2 rendering
> >>
> >
> > If you think Future is not the way to go (and that's what I'd use and I
> > think it covers your problem from in the description you gave) and
> neither
> > ProgressiveDisplay is (which is a good other solution), why don't you
> move
> > the data fetch logic for all components in a single place (preferably a
> > service, maybe the page) so you can properly parallelize it and the
> > components themselves just receive the data instead of fetching it?
> >
> >
> >
> >> On Tue, Apr 14, 2015 at 3:17 PM, Тимур Бухараев <bukhar...@gmail.com>
> >> wrote:
> >>
> >>  Hello,
> >>>
> >>> Future would not helps, because components renders one after one.
> >>> For example page contains component1 and component2.
> >>>
> >>> The render sequence is next:
> >>>
> >>> component1.setupRender();
> >>> other component1 rendering
> >>> component1.setupRender();
> >>> other component2 rendering
> >>>
> >>> So if i create Future in setupRender and get result, i get delay1 in
> >>> rendering component1, and delay2 in rendering component2. Overall delay
> >>> would be delay1+delay2.
> >>> If page is complex and contains many independent components which call
> >>> many remote services, overall delay could be very much.
> >>>
> >>>
> >>> Thank you and Chris for ProgressiveDisplay recommending, i'll look it.
> >>>
> >>> On Tue, Apr 14, 2015 at 3:00 PM, Dmitry Gusev <dmitry.gu...@gmail.com>
> >>> wrote:
> >>>
> >>>  Hi,
> >>>>
> >>>> could you create a Future in your setupRender and use actual results
> w/
> >>>> Future.get() during the rendering?
> >>>>
> >>>> As Chris said I'd also recommend you looking at the ProgressiveDisplay
> >>>> component.
> >>>>
> >>>>
> >>>>
> >>>> On Tue, Apr 14, 2015 at 2:56 PM, Тимур Бухараев <bukhar...@gmail.com>
> >>>> wrote:
> >>>>
> >>>> > I can't call both in setupRender, because i need one blocking wait
> to
> >>>> > receive all requests in parallel.
> >>>> >
> >>>> > Steps:
> >>>> > 1. prepareData(), all components send their request for data,
> remember
> >>>> all
> >>>> > requests.
> >>>> > 2. setupRender(), all components gets data from tokens. getData()
> >>>> could
> >>>> be
> >>>> > like this:
> >>>> >    Response getData() {
> >>>> >        while ( !allRequestsAreRecieved() ) {
> >>>> >            Thread.sleep( 10 );
> >>>> >        }
> >>>> >        return data;
> >>>> >    }
> >>>> >
> >>>> > Now, we if we need 3 data: data1, data2, data3, we dont wait on
> >>>> blocking
> >>>> > calls 3 times one after one. We do one blocking call. So overall
> delay
> >>>> > would be max( delay1. delay2, delay3), not delay1 + delay2 + delay3
> >>>> >
> >>>> > On Tue, Apr 14, 2015 at 2:39 PM, Chris Poulsen <
> >>>> mailingl...@nesluop.dk>
> >>>> > wrote:
> >>>> >
> >>>> > > Or maybe you can use progressive display?
> >>>> > >
> >>>> > >
> >>>> >
> >>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/
> >>>> progressivedisplayvariations
> >>>> > >
> >>>> > > On Tue, Apr 14, 2015 at 1:36 PM, Chris Poulsen <
> >>>> mailingl...@nesluop.dk>
> >>>> > > wrote:
> >>>> > >
> >>>> > > > If your prepareData() is non-blocking, why not just call it
> right
> >>>> > before
> >>>> > > > you do the token.getData() ? (both in setupRender() )
> >>>> > > >
> >>>> > > > On Tue, Apr 14, 2015 at 1:03 PM, Тимур Бухараев <
> >>>> bukhar...@gmail.com>
> >>>> > > > wrote:
> >>>> > > >
> >>>> > > >> Hi,
> >>>> > > >>
> >>>> > > >> My pages consist page class and several components inside.
> >>>> > > >>
> >>>> > > >> Page and its components needs some information from remote
> >>>> services. I
> >>>> > > get
> >>>> > > >> this information with blocking calls in setupRender(). For
> >>>> example,
> >>>> > if i
> >>>> > > >> need user's profile data, i get it like this:
> >>>> > > >>
> >>>> > > >> setupRender() {
> >>>> > > >>  profileData = loadProfileDate(); // blocking call, waiting for
> >>>> the
> >>>> > > >> response
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> And now i can use profileData in render to show some
> information.
> >>>> > > >>
> >>>> > > >> The problem is page and components need many remote data, so
> >>>> there
> >>>> are
> >>>> > > >> many
> >>>> > > >> serial requests to remote services. It harms latency, because
> >>>> overall
> >>>> > > >> latency is sum of serial requests delays.
> >>>> > > >>
> >>>> > > >> I have idea to improve latency, sending requests in parallel. I
> >>>> want
> >>>> > > make
> >>>> > > >> non blocking function sendRequest, which returns me token. All
> >>>> > > components
> >>>> > > >> call non blocking sendRequest for remote data, then i'll wait
> in
> >>>> > > blocking
> >>>> > > >> call waitResponses(), which wait for all responses.Then
> component
> >>>> get
> >>>> > > >> their
> >>>> > > >> data from token.
> >>>> > > >>
> >>>> > > >> Some code for illustration:
> >>>> > > >>
> >>>> > > >> MyComponent {
> >>>> > > >>     @Inject
> >>>> > > >>     private RemoteService remoteService;
> >>>> > > >>
> >>>> > > >>     private Token<Response> token;
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> void prepareData() {
> >>>> > > >>     token = remoteService.sendRequest(); // non blocking call
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> void setupRender() {
> >>>> > > >>     Response response = token.getData(); // first call is
> >>>> blocking,
> >>>> > wait
> >>>> > > >> for all responses, other calls just return data;
> >>>> > > >> }
> >>>> > > >>
> >>>> > > >> Why i did not just realize my idea and write this post?
> >>>> > > >>
> >>>> > > >> Because i need two separate phases: first for send request, and
> >>>> second
> >>>> > > for
> >>>> > > >> prepare rendering. All componets should send in first phase,
> and
> >>>> after
> >>>> > > get
> >>>> > > >> data in second.
> >>>> > > >>
> >>>> > > >> Tapestry have setupRender and beginRender, but they have
> another
> >>>> > order.
> >>>> > > It
> >>>> > > >> call setupRender and beginRender for first component, and then
> -
> >>>> for
> >>>> > > >> second. But i need phase 1 calls for all components, then
> phase 2
> >>>> call
> >>>> > > for
> >>>> > > >> all components.
> >>>> > > >>
> >>>> > > >> And now my question is: is there any way in Tapestry to create
> >>>> this
> >>>> > > >> phases?
> >>>> > > >> Thank you for your attention, sorry for my English.
> >>>> > > >>
> >>>> > > >
> >>>> > > >
> >>>> > >
> >>>> >
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Dmitry Gusev
> >>>>
> >>>> AnjLab Team
> >>>> http://anjlab.com
> >>>>
> >>>>
> >>>
> >>>
> >
> > --
> > Thiago H. de Paula Figueiredo
> > Tapestry, Java and Hibernate consultant and developer
> > http://machina.com.br
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
> > For additional commands, e-mail: users-h...@tapestry.apache.org
> >
> >
>

Reply via email to