You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Stephan Windmüller <st...@tu-dortmund.de> on 2014/07/30 12:45:20 UTC
Product-line specific component messages
Hello,
in our Tapestry application we have several product lines which require
a different wording on the pages. My first thought was to provide my own
implementation of the Messages service and set the product line in the
Java Code with something like
messages.setProductLine(ProductLine)
during onActivate and provide different keys like
title-PRODUCT1=Product One
title-PRODUCT2=Product Two
That would work for all messages retrieved by the injected service, but
how can I replace the service which is used to parse messages in the TML
files? Sadly I was not able to determine the code which is called when
messages are parsed here. Is it handled by AbstractMessages, too?
Regards
Stephan
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Wed, 30 Jul 2014 12:05:13 -0300, Stephan Windmüller
<st...@tu-dortmund.de> wrote:
> It worked! Thank you very very much!
Yay! Never done that myself. :p
> I had to extend AbstractBinding though, because LiteralBinding stores
> fixed values which are never altered.
Good catch. :)
> Currently I am passing both Messages and my own service to the
> construcor of my binding class in order to access these whenever get()
> is called. Is this the right way to do this?
I see no problem in that.
--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Stephan Windmüller <st...@tu-dortmund.de>.
On 30.07.2014, Thiago H de Paula Figueiredo wrote:
> So, if you don't override this method, AbstractBinding subclasses are
> invariant and values get cached for performance.
>
> Create a VariantLiteralBinding subclass that overrides isInvariant() to
> return false, use instead of LiteralBinding and I guess it'll work.
It worked! Thank you very very much!
I had to extend AbstractBinding though, because LiteralBinding stores
fixed values which are never altered.
Currently I am passing both Messages and my own service to the
construcor of my binding class in order to access these whenever get()
is called. Is this the right way to do this?
Regards
Stephan
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Wed, 30 Jul 2014 10:42:39 -0300, Stephan Windmüller
<st...@tu-dortmund.de> wrote:
>>> Injecting the service in onActivate and setting the value does not
>>> work.
>> Define "does not work". Did you debug your binding factory?
>
> Yes, and it seems that "newBinding" is only called once for each
> location and the value is cached. But more importantly, newBinding is
> called _before_ the onActivate method is evaluated.
>
> In other words: It seems that it is not possible to change evaluated
> value from onActivate.
We can prevent that. Look at the Binding interface: it has this method:
/**
* Returns true if the value of the binding does not ever change.
Components will often cache such values
* aggressively.
*/
boolean isInvariant();
Then at AbstractBinding:
/**
* Returns true. Subclasses that do not supply a fixed, read-only
value should override this method to return
* false.
*/
public boolean isInvariant()
{
return true;
}
So, if you don't override this method, AbstractBinding subclasses are
invariant and values get cached for performance.
Create a VariantLiteralBinding subclass that overrides isInvariant() to
return false, use instead of LiteralBinding and I guess it'll work.
--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Stephan Windmüller <st...@tu-dortmund.de>.
Am 30.07.2014 um 15:18 schrieb Thiago H de Paula Figueiredo:
> Don't forget productService must be a perthread service. Otherwise, any
> request for the current product will set it for all others and a mess will
> arise.
I can imagine that. ;)
To prevent this, I added "@Scope(ScopeConstants.PERTHREAD)" to the
ProductServiceImpl class.
>> Injecting the service in onActivate and setting the value does not work.
> Define "does not work". Did you debug your binding factory?
Yes, and it seems that "newBinding" is only called once for each
location and the value is cached. But more importantly, newBinding is
called _before_ the onActivate method is evaluated.
In other words: It seems that it is not possible to change evaluated
value from onActivate.
Regards
Stephan
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Wed, 30 Jul 2014 10:02:55 -0300, Stephan Windmüller
<st...@tu-dortmund.de> wrote:
> And here is my problem: The current product is selected based on the
> activation context. How can I modify the service based on the values of
> the context?
@Inject
private ProductService productService;
void onActivate(...) {
productService.setCurrentProduct(...);
}
Don't forget productService must be a perthread service. Otherwise, any
request for the current product will set it for all others and a mess will
arise.
> Injecting the service in onActivate and setting the value does not work.
Define "does not work". Did you debug your binding factory?
--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Stephan Windmüller <st...@tu-dortmund.de>.
Am 30.07.2014 um 14:14 schrieb Thiago H de Paula Figueiredo:
> Why don't you create your own 'productmessage' binding so you can write
> ${productmessage:title} and have it treated like you wrote
> messages.get("title")?
That looks really promising, thank you for the detailed explanation!
> Here's an untested version of your ProductMessageBindingFactory, supposing
> you have a ProductService perthread service which provides the current
> product:
And here is my problem: The current product is selected based on the
activation context. How can I modify the service based on the values of
the context?
Injecting the service in onActivate and setting the value does not work.
Regards
Stephan
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org
Re: Product-line specific component messages
Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Wed, 30 Jul 2014 07:45:20 -0300, Stephan Windmüller
<st...@tu-dortmund.de> wrote:
> Hello,
Hi!
>
> in our Tapestry application we have several product lines which require
> a different wording on the pages. My first thought was to provide my own
> implementation of the Messages service and set the product line in the
> Java Code with something like
>
> messages.setProductLine(ProductLine)
>
> during onActivate and provide different keys like
>
> title-PRODUCT1=Product One
> title-PRODUCT2=Product Two
Why don't you create your own 'productmessage' binding so you can write
${productmessage:title} and have it treated like you wrote
messages.get("title")?
> That would work for all messages retrieved by the injected service, but
> how can I replace the service which is used to parse messages in the TML
> files?
The Tapestry template parser does *not* parse messages. Actually, it just
parses ${} expansions and ask their values to the specified binding. The
'message' binding is the one who actually handles the messages. Here's its
implementation:
public class MessageBindingFactory implements BindingFactory
{
public Binding newBinding(String description, ComponentResources
container, ComponentResources component,
String expression, Location location)
{
String messageValue = container.getMessages().get(expression);
return new LiteralBinding(location, description, messageValue);
}
}
Incredibly simple, isn't it? :)
Here's an untested version of your ProductMessageBindingFactory, supposing
you have a ProductService perthread service which provides the current
product:
public class ProductMessageBindingFactory implements BindingFactory
{
final private ProductService productService;
public ProductMessageBindingFactory(ProductService productService) {
this.productService = productService;
}
public Binding newBinding(String description, ComponentResources
container, ComponentResources component,
String expression, Location location)
{
String messageValue = container.getMessages().get(expression + "-"
+ productService.getCurrentProductMessageSuffix());
return new LiteralBinding(location, description, messageValue);
}
}
Then, in your AppModule class (or any other Tapestry-IoC module class),
contribute it to BindingSource:
public static void contributeBindingSource(MappedConfiguration<String,
BindingFactory> configuration) {
configuration.addInstance("productmessages",
ProductMessageBindingFactory.class);
}
And that's it.
--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org