eventlink with multiple context parameters

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

eventlink with multiple context parameters

D.R.-2
Hi @all,

I am confused about calling a java method with an eventlink and multiple
context parameters:
t:context="[account.get('test').userUuid, friend]" does not work, see
below please.

Following stuff is in my Java class:

@Property(write = false)
private final String friend = "friend";
public AbstractMap<String, UserAccount> getAccount() {
     UserAccount userAcc = userAccounts.get(loopContactIndex);
     AbstractMap<String, UserAccount> test = new HashMap<String,
UserAccount>();
     test.put("test", userAcc);
     return test;
}

void onChangeRelation(final String uuid, final String relation) {
     // no chance to come inside here...
}


void onForget(final String uuid) {
        // everything ok here...
}

It is no problem to call "onForget" with this eventlink:
     <t:eventlink t:event="forget" t:async="true"
t:context="account.get('test').userUuid"> Forget </t:eventlink>

But if I try to call an eventlink like:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.get('test').userUuid, friend]"> Change Relation
</t:eventlink>

then I get following exception:

Exception assembling root component of page profile/User: Exception
assembling embedded component 'usercontactlist' (of type
com.myapp.t5.components.profile.UserContactList, within profile/User):
Could not convert '[account.get('test').userUuid, friend]' into a
component parameter binding: Exception generating conduit for expression
'[account.get('test').userUuid, friend]': Class java.lang.Object does
not contain a property (or public field) named 'userUuid'.

Now I tried this eventlink:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[${account.get('test').userUuid}, friend]"> Change Relation
</t:eventlink>
And the page loads successful.

But a click on this eventlink, calls the wrong method with only one
parameter which is converted to java.lang.String:

void onChangeRelation(final Object param) {
     System.out.println(param.getClass().getName() + ": " + param);
}

Console --> java.lang.String: [018260e7-844c-44a5-aefc-12faa80de42c, friend]

means t:context="[${account.get('test').userUuid}, friend]" is
interpreted as a String.

if I remove the Map and return UserAccount directly in "getAccount()"
the code works great:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.userUuid, friend]"> Change Relation </t:eventlink>

Furthermore I tried to replace the AbstractMap with Optional class:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.get().userUuid, friend]"> Change Relation </t:eventlink>

With this I get the same exception:

Exception assembling root component of page profile/User: Exception
assembling embedded component 'usercontactlist' (of type
com.myapp.t5.components.profile.UserContactList, within profile/User):
Could not convert '[account.get().userUuid, friend]' into a component
parameter binding: Exception generating conduit for expression
'[account.get().userUuid, friend]': Class java.lang.Object does not
contain a property (or public field) named 'userUuid'.

Why the second level is treated as Object, if i want to get a value in
the third level?
(i know, we could solve that by providing another getter in the java
class, but this violates "code less, deliver more" :-)
Why does this occur only in case of an eventlink with multiple parameters?
What i am doing wrong?

Thanks for help!


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

Reply | Threaded
Open this post in threaded view
|

Re: eventlink with multiple context parameters

Chris Poulsen
I think that you may be hit by some type erasure on the map. That said
Tapestry also has some correctness issues with some generic constructs
where it detects a too generic type in some complex cases.

We are overriding the GenericsUtils class with an implementation that uses
Guava's TypeToken for most of its generics work - That improves the
situation a lot, but if your example code is what you actually use, then
that is probably not the issue here.

In this case I think that you would be best off setting up the eventlink
context in java code. IMO it is better style to have all but the most
simple expressions in the Java class and if you build the Object[]  (the
entire parameter value, not its "parts") in Java, this is not an issue to
begin with.

--
Chris

On Tue, Oct 2, 2018 at 4:48 PM D. R. <[hidden email]> wrote:

> Hi @all,
>
> I am confused about calling a java method with an eventlink and multiple
> context parameters:
> t:context="[account.get('test').userUuid, friend]" does not work, see
> below please.
>
> Following stuff is in my Java class:
>
> @Property(write = false)
> private final String friend = "friend";
> public AbstractMap<String, UserAccount> getAccount() {
>      UserAccount userAcc = userAccounts.get(loopContactIndex);
>      AbstractMap<String, UserAccount> test = new HashMap<String,
> UserAccount>();
>      test.put("test", userAcc);
>      return test;
> }
>
> void onChangeRelation(final String uuid, final String relation) {
>      // no chance to come inside here...
> }
>
>
> void onForget(final String uuid) {
>         // everything ok here...
> }
>
> It is no problem to call "onForget" with this eventlink:
>      <t:eventlink t:event="forget" t:async="true"
> t:context="account.get('test').userUuid"> Forget </t:eventlink>
>
> But if I try to call an eventlink like:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.get('test').userUuid, friend]"> Change Relation
> </t:eventlink>
>
> then I get following exception:
>
> Exception assembling root component of page profile/User: Exception
> assembling embedded component 'usercontactlist' (of type
> com.myapp.t5.components.profile.UserContactList, within profile/User):
> Could not convert '[account.get('test').userUuid, friend]' into a
> component parameter binding: Exception generating conduit for expression
> '[account.get('test').userUuid, friend]': Class java.lang.Object does
> not contain a property (or public field) named 'userUuid'.
>
> Now I tried this eventlink:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[${account.get('test').userUuid}, friend]"> Change Relation
> </t:eventlink>
> And the page loads successful.
>
> But a click on this eventlink, calls the wrong method with only one
> parameter which is converted to java.lang.String:
>
> void onChangeRelation(final Object param) {
>      System.out.println(param.getClass().getName() + ": " + param);
> }
>
> Console --> java.lang.String: [018260e7-844c-44a5-aefc-12faa80de42c,
> friend]
>
> means t:context="[${account.get('test').userUuid}, friend]" is
> interpreted as a String.
>
> if I remove the Map and return UserAccount directly in "getAccount()"
> the code works great:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.userUuid, friend]"> Change Relation </t:eventlink>
>
> Furthermore I tried to replace the AbstractMap with Optional class:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.get().userUuid, friend]"> Change Relation
> </t:eventlink>
>
> With this I get the same exception:
>
> Exception assembling root component of page profile/User: Exception
> assembling embedded component 'usercontactlist' (of type
> com.myapp.t5.components.profile.UserContactList, within profile/User):
> Could not convert '[account.get().userUuid, friend]' into a component
> parameter binding: Exception generating conduit for expression
> '[account.get().userUuid, friend]': Class java.lang.Object does not
> contain a property (or public field) named 'userUuid'.
>
> Why the second level is treated as Object, if i want to get a value in
> the third level?
> (i know, we could solve that by providing another getter in the java
> class, but this violates "code less, deliver more" :-)
> Why does this occur only in case of an eventlink with multiple parameters?
> What i am doing wrong?
>
> Thanks for help!
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

RE: eventlink with multiple context parameters

Ross, Cyndy
In reply to this post by D.R.-2

try
 <t:eventlink t:event="changeRelation" t:async="true"
t:context="list:account.get('test').userUuid, friend"> Change Relation
</t:eventlink>

square brackets doesn't work for me either.  not sure why list: is not documented.

cheers,
Cyndy
________________________________________
From: D. R. [[hidden email]]
Sent: Tuesday, October 02, 2018 10:48 AM
To: [hidden email]
Subject: eventlink with multiple context parameters

Hi @all,

I am confused about calling a java method with an eventlink and multiple
context parameters:
t:context="[account.get('test').userUuid, friend]" does not work, see
below please.

Following stuff is in my Java class:

@Property(write = false)
private final String friend = "friend";
public AbstractMap<String, UserAccount> getAccount() {
     UserAccount userAcc = userAccounts.get(loopContactIndex);
     AbstractMap<String, UserAccount> test = new HashMap<String,
UserAccount>();
     test.put("test", userAcc);
     return test;
}

void onChangeRelation(final String uuid, final String relation) {
     // no chance to come inside here...
}


void onForget(final String uuid) {
        // everything ok here...
}

It is no problem to call "onForget" with this eventlink:
     <t:eventlink t:event="forget" t:async="true"
t:context="account.get('test').userUuid"> Forget </t:eventlink>

But if I try to call an eventlink like:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.get('test').userUuid, friend]"> Change Relation
</t:eventlink>

then I get following exception:

Exception assembling root component of page profile/User: Exception
assembling embedded component 'usercontactlist' (of type
com.myapp.t5.components.profile.UserContactList, within profile/User):
Could not convert '[account.get('test').userUuid, friend]' into a
component parameter binding: Exception generating conduit for expression
'[account.get('test').userUuid, friend]': Class java.lang.Object does
not contain a property (or public field) named 'userUuid'.

Now I tried this eventlink:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[${account.get('test').userUuid}, friend]"> Change Relation
</t:eventlink>
And the page loads successful.

But a click on this eventlink, calls the wrong method with only one
parameter which is converted to java.lang.String:

void onChangeRelation(final Object param) {
     System.out.println(param.getClass().getName() + ": " + param);
}

Console --> java.lang.String: [018260e7-844c-44a5-aefc-12faa80de42c, friend]

means t:context="[${account.get('test').userUuid}, friend]" is
interpreted as a String.

if I remove the Map and return UserAccount directly in "getAccount()"
the code works great:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.userUuid, friend]"> Change Relation </t:eventlink>

Furthermore I tried to replace the AbstractMap with Optional class:
     <t:eventlink t:event="changeRelation" t:async="true"
t:context="[account.get().userUuid, friend]"> Change Relation </t:eventlink>

With this I get the same exception:

Exception assembling root component of page profile/User: Exception
assembling embedded component 'usercontactlist' (of type
com.myapp.t5.components.profile.UserContactList, within profile/User):
Could not convert '[account.get().userUuid, friend]' into a component
parameter binding: Exception generating conduit for expression
'[account.get().userUuid, friend]': Class java.lang.Object does not
contain a property (or public field) named 'userUuid'.

Why the second level is treated as Object, if i want to get a value in
the third level?
(i know, we could solve that by providing another getter in the java
class, but this violates "code less, deliver more" :-)
Why does this occur only in case of an eventlink with multiple parameters?
What i am doing wrong?

Thanks for help!


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


---------------------------------------------------------------------------------------
 This email has been scanned for email related threats and delivered safely by Mimecast.
 For more information please visit http://www.mimecast.com
---------------------------------------------------------------------------------------
Reply | Threaded
Open this post in threaded view
|

Re: eventlink with multiple context parameters

Thiago H de Paula Figueiredo
I don't think the list: prefix is part of Tapestry itself, but of a
third-party module. Anyway, any context not dead simple is better served by
being done in Java instead of the template. That's the Tapestry philosophy.

On Wed, Oct 3, 2018 at 4:17 PM Ross, Cyndy <[hidden email]> wrote:

>
> try
>  <t:eventlink t:event="changeRelation" t:async="true"
> t:context="list:account.get('test').userUuid, friend"> Change Relation
> </t:eventlink>
>
> square brackets doesn't work for me either.  not sure why list: is not
> documented.
>
> cheers,
> Cyndy
> ________________________________________
> From: D. R. [[hidden email]]
> Sent: Tuesday, October 02, 2018 10:48 AM
> To: [hidden email]
> Subject: eventlink with multiple context parameters
>
> Hi @all,
>
> I am confused about calling a java method with an eventlink and multiple
> context parameters:
> t:context="[account.get('test').userUuid, friend]" does not work, see
> below please.
>
> Following stuff is in my Java class:
>
> @Property(write = false)
> private final String friend = "friend";
> public AbstractMap<String, UserAccount> getAccount() {
>      UserAccount userAcc = userAccounts.get(loopContactIndex);
>      AbstractMap<String, UserAccount> test = new HashMap<String,
> UserAccount>();
>      test.put("test", userAcc);
>      return test;
> }
>
> void onChangeRelation(final String uuid, final String relation) {
>      // no chance to come inside here...
> }
>
>
> void onForget(final String uuid) {
>         // everything ok here...
> }
>
> It is no problem to call "onForget" with this eventlink:
>      <t:eventlink t:event="forget" t:async="true"
> t:context="account.get('test').userUuid"> Forget </t:eventlink>
>
> But if I try to call an eventlink like:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.get('test').userUuid, friend]"> Change Relation
> </t:eventlink>
>
> then I get following exception:
>
> Exception assembling root component of page profile/User: Exception
> assembling embedded component 'usercontactlist' (of type
> com.myapp.t5.components.profile.UserContactList, within profile/User):
> Could not convert '[account.get('test').userUuid, friend]' into a
> component parameter binding: Exception generating conduit for expression
> '[account.get('test').userUuid, friend]': Class java.lang.Object does
> not contain a property (or public field) named 'userUuid'.
>
> Now I tried this eventlink:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[${account.get('test').userUuid}, friend]"> Change Relation
> </t:eventlink>
> And the page loads successful.
>
> But a click on this eventlink, calls the wrong method with only one
> parameter which is converted to java.lang.String:
>
> void onChangeRelation(final Object param) {
>      System.out.println(param.getClass().getName() + ": " + param);
> }
>
> Console --> java.lang.String: [018260e7-844c-44a5-aefc-12faa80de42c,
> friend]
>
> means t:context="[${account.get('test').userUuid}, friend]" is
> interpreted as a String.
>
> if I remove the Map and return UserAccount directly in "getAccount()"
> the code works great:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.userUuid, friend]"> Change Relation </t:eventlink>
>
> Furthermore I tried to replace the AbstractMap with Optional class:
>      <t:eventlink t:event="changeRelation" t:async="true"
> t:context="[account.get().userUuid, friend]"> Change Relation
> </t:eventlink>
>
> With this I get the same exception:
>
> Exception assembling root component of page profile/User: Exception
> assembling embedded component 'usercontactlist' (of type
> com.myapp.t5.components.profile.UserContactList, within profile/User):
> Could not convert '[account.get().userUuid, friend]' into a component
> parameter binding: Exception generating conduit for expression
> '[account.get().userUuid, friend]': Class java.lang.Object does not
> contain a property (or public field) named 'userUuid'.
>
> Why the second level is treated as Object, if i want to get a value in
> the third level?
> (i know, we could solve that by providing another getter in the java
> class, but this violates "code less, deliver more" :-)
> Why does this occur only in case of an eventlink with multiple parameters?
> What i am doing wrong?
>
> Thanks for help!
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
>
> ---------------------------------------------------------------------------------------
>  This email has been scanned for email related threats and delivered
> safely by Mimecast.
>  For more information please visit http://www.mimecast.com
>
> ---------------------------------------------------------------------------------------
>


--
Thiago