You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Numa Schmeder <nu...@dfacto.ch> on 2021/06/17 10:20:32 UTC

Help overriding ComponentMessageSource service

Hello,

I am trying to override the ComponentMessageSource service with a custom ComponentMessageSourceImpl. The main reason to override the service is to be able to use a custom implementation of MapMessages in MessageFormatterImpl.
Currently it uses only String Formatter, which is very good for some time of formatting but less practical for i18n formatting as it doesn’t handle plurals at all. I would like to revert to classic MessageFormat.

This is what I have done in my module:
@Contribute(ServiceOverride.class)
public static void setupApplicationServiceOverrides(MappedConfiguration<Class<?>,Object> configuration, @Local ComponentMessagesSource messagesSource)
{
    //  configuration.add(HibernateSessionSource.class, hibernateSessionSource);
    //overriding existing default component message source to add MessageFormat
    configuration.override(ComponentMessagesSource.class, messagesSource);

}

public static ComponentMessagesSource buildCustomComponentMessagesSource(UpdateListenerHub updateListenerHub, @Autobuild ComponentMessagesSourceImpl service)
{
    updateListenerHub.addUpdateListener(service);
    return service;
}

If anyone has a clue on how to override this service this would be very helpful. I always end up with 2 conflicting service, and configuration.override doesn’t work. 
It tapestry module ComponentMessageSource is built using a builder method and then injected
public static ComponentMessagesSource buildComponentMessagesSource(UpdateListenerHub updateListenerHub, @Autobuild ComponentMessagesSourceImpl service)
{
    updateListenerHub.addUpdateListener(service);
    return service;
}

Thank you for your help :)

Best regards, 

  <http://www.dfacto.ch/>	Numa Schmeder    www.dfacto.ch  <http://www.dfacto.ch/>
NUMA@DFACTO.CH <ma...@dfacto.ch>   |   M +41 79 538 30 01 

DIGITAL STRATEGY   |   DESIGN   |   DEVELOPMENT


 


Re: Help overriding ComponentMessageSource service

Posted by Numa Schmeder <nu...@dfacto.ch>.
Hi,

Thanks for you help!
So the ServiceOverride solution doesn’t work, you get a recursive exception!
Construction of service 'ServiceOverride' has failed due to recursion: the service depends on itself in some way.

But the decorate works, it’s fine for me that way. I will add a Jira issue. 

Best regards,

  <http://www.dfacto.ch/>	Numa Schmeder    www.dfacto.ch  <http://www.dfacto.ch/>
NUMA@DFACTO.CH <ma...@dfacto.ch>   |   M +41 79 538 30 01 

DIGITAL STRATEGY   |   DESIGN   |   DEVELOPMENT


 

> Le 21 juin 2021 à 14:13, Thiago H. de Paula Figueiredo <th...@gmail.com> a écrit :
> 
> On Thu, Jun 17, 2021 at 8:29 AM Numa Schmeder <nu...@dfacto.ch> wrote:
> 
>> Hi,
> 
> 
> Hi!
> 
> 
>> Thanks for your help, no it doesn’t seem to work.  I found a solution
>> using decorate method, but I am not sure it’s really clean.
> 
> 
> I consider decoration really clean. Sometimes you cannot use service
> override because it causes a circular service dependency (it ends up
> depending on itself).
> 
> 
>> public static ComponentMessagesSource
>> decorateComponentMessagesSource(ComponentMessagesSource current, @Autobuild
>> CustomComponentMessagesSourceImpl custom, UpdateListenerHub
>> updateListenerHub)
>> {
>>    updateListenerHub.addUpdateListener(custom);
>>    return custom;
>> }
>> 
> 
> This looks good to me.
> 
> 
>> Just wondering if there is no cleaner way.
> 
> 
> I guess your problem in your original attempt was declaring your custom
> messages source as a service, something you don't need. That way, you end
> up with two services implementing the same service interface and
> Tapestry-IoC doesn't know which one to use.
> 
> I'd try this:
> 
> @Contribute(ServiceOverride.class)
> public static void
> setupApplicationServiceOverrides(MappedConfiguration<Class<?>,Object>
> configuration, @Autobuild YourCustomComponentMessagesSource messagesSource,
> UpdateListenerHub updateListenerHub)
> {
>    //  configuration.add(HibernateSessionSource.class,
> hibernateSessionSource);
>    //overriding existing default component message source to add
> MessageFormat
>    updateListenerHub.addUpdateListener(messagesSource);
>    configuration.override(ComponentMessagesSource.class, messagesSource);
> }
> 
> 
>> I believe message formatter should be a service that should be overridable.
> 
> 
> Please create a Jira issue for this.
> 
> --
> Thiago


Re: Help overriding ComponentMessageSource service

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
On Thu, Jun 17, 2021 at 8:29 AM Numa Schmeder <nu...@dfacto.ch> wrote:

> Hi,


Hi!


> Thanks for your help, no it doesn’t seem to work.  I found a solution
> using decorate method, but I am not sure it’s really clean.


I consider decoration really clean. Sometimes you cannot use service
override because it causes a circular service dependency (it ends up
depending on itself).


> public static ComponentMessagesSource
> decorateComponentMessagesSource(ComponentMessagesSource current, @Autobuild
> CustomComponentMessagesSourceImpl custom, UpdateListenerHub
> updateListenerHub)
> {
>     updateListenerHub.addUpdateListener(custom);
>     return custom;
> }
>

This looks good to me.


> Just wondering if there is no cleaner way.


I guess your problem in your original attempt was declaring your custom
messages source as a service, something you don't need. That way, you end
up with two services implementing the same service interface and
Tapestry-IoC doesn't know which one to use.

I'd try this:

@Contribute(ServiceOverride.class)
public static void
setupApplicationServiceOverrides(MappedConfiguration<Class<?>,Object>
configuration, @Autobuild YourCustomComponentMessagesSource messagesSource,
UpdateListenerHub updateListenerHub)
{
    //  configuration.add(HibernateSessionSource.class,
hibernateSessionSource);
    //overriding existing default component message source to add
MessageFormat
    updateListenerHub.addUpdateListener(messagesSource);
    configuration.override(ComponentMessagesSource.class, messagesSource);
}


> I believe message formatter should be a service that should be overridable.


Please create a Jira issue for this.

--
Thiago

Re: Help overriding ComponentMessageSource service

Posted by Numa Schmeder <nu...@dfacto.ch>.
Hi, 

Thanks for your help, no it doesn’t seem to work.  I found a solution using decorate method, but I am not sure it’s really clean. 
public static ComponentMessagesSource decorateComponentMessagesSource(ComponentMessagesSource current, @Autobuild CustomComponentMessagesSourceImpl custom, UpdateListenerHub updateListenerHub)
{
    updateListenerHub.addUpdateListener(custom);
    return custom;
}
Just wondering if there is no cleaner way. 
I believe message formatter should be a service that should be overridable. 

My implementation works as follow if it detects in the format a MessageFormat pattern it will use a customer formatter, otherwise it will use the default MessageFormatterImpl.

Inside MapMessages:

private MessageFormatter buildMessageFormatter(String key)
{
    String format = get(key);
    if (MESSAGE_FORMAT_PATTERN.matcher(format).find()) {
        return new CustomMessageFormatterImpl(format, locale);
    }
    return new MessageFormatterImpl(format, locale);
}


> Le 17 juin 2021 à 12:41, Volker Lamp <vo...@gmail.com> a écrit :
> 
> Hello Numa,
> 
> I think you are missing withId() in your binder method to assign a unique
> name.
> 
> See https://tapestry.apache.org/ioc-cookbook-overriding-ioc-services.html <https://tapestry.apache.org/ioc-cookbook-overriding-ioc-services.html>
> 
> Cheers,
> 
> Volker
> 
> 
> Am Do., 17. Juni 2021 um 12:20 Uhr schrieb Numa Schmeder <numa@dfacto.ch <ma...@dfacto.ch>>:
> 
>> Hello,
>> 
>> I am trying to override the ComponentMessageSource service with a custom
>> ComponentMessageSourceImpl. The main reason to override the service is to
>> be able to use a custom implementation of MapMessages in
>> MessageFormatterImpl.
>> Currently it uses only String Formatter, which is very good for some time
>> of formatting but less practical for i18n formatting as it doesn’t handle
>> plurals at all. I would like to revert to classic MessageFormat.
>> 
>> This is what I have done in my module:
>> @Contribute(ServiceOverride.class)
>> public static void
>> setupApplicationServiceOverrides(MappedConfiguration<Class<?>,Object>
>> configuration, @Local ComponentMessagesSource messagesSource)
>> {
>>    //  configuration.add(HibernateSessionSource.class,
>> hibernateSessionSource);
>>    //overriding existing default component message source to add
>> MessageFormat
>>    configuration.override(ComponentMessagesSource.class, messagesSource);
>> 
>> }
>> 
>> public static ComponentMessagesSource
>> buildCustomComponentMessagesSource(UpdateListenerHub updateListenerHub,
>> @Autobuild ComponentMessagesSourceImpl service)
>> {
>>    updateListenerHub.addUpdateListener(service);
>>    return service;
>> }
>> 
>> If anyone has a clue on how to override this service this would be very
>> helpful. I always end up with 2 conflicting service, and
>> configuration.override doesn’t work.
>> It tapestry module ComponentMessageSource is built using a builder method
>> and then injected
>> public static ComponentMessagesSource
>> buildComponentMessagesSource(UpdateListenerHub updateListenerHub,
>> @Autobuild ComponentMessagesSourceImpl service)
>> {
>>    updateListenerHub.addUpdateListener(service);
>>    return service;
>> }
>> 
>> Thank you for your help :)
>> 
>> Best regards,
>> 
>>  <http://www.dfacto.ch/ <http://www.dfacto.ch/>>       Numa Schmeder    www.dfacto.ch <http://www.dfacto.ch/>  <
>> http://www.dfacto.ch/ <http://www.dfacto.ch/>>
>> NUMA@DFACTO.CH <ma...@DFACTO.CH> <mailto:numa@dfacto.ch <ma...@dfacto.ch>>   |   M +41 79 538 30 01
>> 
>> DIGITAL STRATEGY   |   DESIGN   |   DEVELOPMENT


Re: Help overriding ComponentMessageSource service

Posted by Volker Lamp <vo...@gmail.com>.
Hello Numa,

I think you are missing withId() in your binder method to assign a unique
name.

See https://tapestry.apache.org/ioc-cookbook-overriding-ioc-services.html

Cheers,

Volker


Am Do., 17. Juni 2021 um 12:20 Uhr schrieb Numa Schmeder <nu...@dfacto.ch>:

> Hello,
>
> I am trying to override the ComponentMessageSource service with a custom
> ComponentMessageSourceImpl. The main reason to override the service is to
> be able to use a custom implementation of MapMessages in
> MessageFormatterImpl.
> Currently it uses only String Formatter, which is very good for some time
> of formatting but less practical for i18n formatting as it doesn’t handle
> plurals at all. I would like to revert to classic MessageFormat.
>
> This is what I have done in my module:
> @Contribute(ServiceOverride.class)
> public static void
> setupApplicationServiceOverrides(MappedConfiguration<Class<?>,Object>
> configuration, @Local ComponentMessagesSource messagesSource)
> {
>     //  configuration.add(HibernateSessionSource.class,
> hibernateSessionSource);
>     //overriding existing default component message source to add
> MessageFormat
>     configuration.override(ComponentMessagesSource.class, messagesSource);
>
> }
>
> public static ComponentMessagesSource
> buildCustomComponentMessagesSource(UpdateListenerHub updateListenerHub,
> @Autobuild ComponentMessagesSourceImpl service)
> {
>     updateListenerHub.addUpdateListener(service);
>     return service;
> }
>
> If anyone has a clue on how to override this service this would be very
> helpful. I always end up with 2 conflicting service, and
> configuration.override doesn’t work.
> It tapestry module ComponentMessageSource is built using a builder method
> and then injected
> public static ComponentMessagesSource
> buildComponentMessagesSource(UpdateListenerHub updateListenerHub,
> @Autobuild ComponentMessagesSourceImpl service)
> {
>     updateListenerHub.addUpdateListener(service);
>     return service;
> }
>
> Thank you for your help :)
>
> Best regards,
>
>   <http://www.dfacto.ch/>       Numa Schmeder    www.dfacto.ch  <
> http://www.dfacto.ch/>
> NUMA@DFACTO.CH <ma...@dfacto.ch>   |   M +41 79 538 30 01
>
> DIGITAL STRATEGY   |   DESIGN   |   DEVELOPMENT
>
>
>
>
>