Expand my Community achievements bar.

SOLVED

AEM 5.6.1, injecting ResourceBundleProvider, expecting JcrResourceBundleProvider but getting PseudoTranslations implementation

Avatar

Former Community Member

We have upgraded from 5.5 SP3 to 5.6.1 and are having problems with getting i18n content using the org.apache.sling.i18n.ResourceBundleProvider interface. We inject a ResourceBundleProvider into a service and the implementation we are getting is com.adobe.granite.i18n.impl.bundle.PseudoTranslations. After having a quick look at this class after decompilation, it looks like some kind of a mock implementation? We would expect some real implementation like JcrResourceBundleProvider.

The i18n bundle we are running after upgrading is (containing the PseudoTranslations implementation)

         
Symbolic Namecom.day.cq.cq-i18n
Version5.5.10
1 Accepted Solution

Avatar

Correct answer by
Employee

Hi,

The purpose of the PseudoTranslations provider is to faciliate testing of components to ensure that all strings are i18n'd. It is actually quite useful.

The problem I suspect is that your code has something like this:

@Reference private ResourceBundleProvider resourceBundleProvider

In CQ 5.5 SP3, there generally only a single service for this interface, although there was no guarantee that would be the case. In CQ 5.6.1, there are two and your component is getting injected with an unexpected implementation (which is what Murphy's law says should happen).

You have two choices. The first is to make your component handle the case where there's more than one ResourceBundleProvider. This is probably not that much work, but it is non-trivial. The second is to add a filter to the @Reference annotation to ensure that the expected service is bound. Something like:

@Reference(filter="(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)") private ResourceBundleProvider resourceBundleProvider

Should do the trick.

Regards,

Justin

View solution in original post

6 Replies

Avatar

Employee

wouthe wrote...

Hi,

I tried using @Reference(filter="(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)"). But, I get an error saying "filter" is not the supported attribute.

Is there any other workaround?

 

Thanks,

 

Apologies, the attribute name is target, not filter.

Avatar

Level 10
AFAIK With 5.6 allows multiple providers. Stop the PseudoTranslations if not utilized & Verify

Avatar

Former Community Member

Thanks, stopping the PseudoTranslations component solved it, but when restarting the instance the component comes back to haunt us... We need to look into how we can stop it permanently then.

Would be interesting to know why this ResourceBundleProvider implementation exists in the product at all?

Avatar

Level 10

[1] should give an idea for that new bundle.

I can provide with an option to stop permanently but I am not confident it is right solution might be better solution exist for this at api level.  If you don;t hear other expert advise please file a daycare ticket. 

[1]  https://issues.apache.org/jira/browse/SLING-2576

Avatar

Correct answer by
Employee

Hi,

The purpose of the PseudoTranslations provider is to faciliate testing of components to ensure that all strings are i18n'd. It is actually quite useful.

The problem I suspect is that your code has something like this:

@Reference private ResourceBundleProvider resourceBundleProvider

In CQ 5.5 SP3, there generally only a single service for this interface, although there was no guarantee that would be the case. In CQ 5.6.1, there are two and your component is getting injected with an unexpected implementation (which is what Murphy's law says should happen).

You have two choices. The first is to make your component handle the case where there's more than one ResourceBundleProvider. This is probably not that much work, but it is non-trivial. The second is to add a filter to the @Reference annotation to ensure that the expected service is bound. Something like:

@Reference(filter="(component.name=org.apache.sling.i18n.impl.JcrResourceBundleProvider)") private ResourceBundleProvider resourceBundleProvider

Should do the trick.

Regards,

Justin

Avatar

Level 10

Thanks justin. I was thinking need to loop through list of ResourceBundleProviders. The filter option looks neat & good.