Expand my Community achievements bar.

SlingModel @ChildResource annotation not using the defaultInjectionStrategy defined at model class level

Avatar

Level 1

I have a sling model in which I am injecting a multifield resources using @ChildResource annotation. This works fine when the multifield has been populated but fails if its not. I have defined the defaultInjectionStrategy as OPTIONAL at class level but its not used, I even tried @Optional annotation but it also doesn't work. However if I provide optional=true to the @ChildResource annotation, the injection works fine in case of absent multifield nodes. 

I am using AEM 6.1 SP1 for running this model. As per the documentation for @ChildResource the optional's use is deprecated, What can I do not use the optional param but use injection strategy to fix the issue. Here is my code - 

@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class HeaderSlingModel { /** * Inject property via resource, named fileReference. */ @Inject @Via("resource") @Named("fileReference") private String qrCodeImage; /** * Inject property via resource, helpCustomerService. */ @Inject @Via("resource") private String helpCustomerService; /** * Inject property via resource, helpDeltaAssist. */ @Inject @Via("resource") private String helpDeltaAssist; /** * Inject property via resource, helpReservationOffice. */ @Inject @Via("resource") private String helpReservationOffice; /** * Inject property via resource, logoLink. */ @Inject @Via("resource") private String logoLink; /** * Inject property via resource, navDepth. */ @Inject @Via("resource") private String navDepth; /** * Inject property via resource, navRootPath. */ @Inject @Via("resource") private String navRootPath; /** * Inject resource list under node quickLink. */ @ChildResource(optional = true) @Optional() private List<Resource> quickLink; /** * Inject resource list under node alert. */ @ChildResource(optional = true) @Optional private List<Resource> alert; /** * Inject resource. */ @Inject private Resource resource; /** * Inject currentPage. */ @Inject private Page currentPage; /** * List of quicklinks. */ private List<QuickLink> quickLinks; /** * List of alerts. */ private List<Alert> alerts; /** * navigation items. */ private List<Navigation> navigation; /** * Processing method. */ @PostConstruct public final void init() { if (null != quickLink && !quickLink.isEmpty()) { quickLinks = quickLink.stream() .map(qLink -> qLink.adaptTo(QuickLink.class)) .collect(Collectors.toList()); } if (null != alert && !alert.isEmpty()) { alerts = alert.stream() .map(entry -> entry.adaptTo(Alert.class)) .collect(Collectors.toList()); } buildNavigation(); } /** * Build the navigation elements. */ private void buildNavigation() { final Resource navRootResource = resource.getResourceResolver().getResource(navRootPath); if (null == navRootResource || ResourceUtil.isNonExistingResource(navRootResource)) { throw new IllegalArgumentException(format("Could not get resource for navigation root at path %s", navRootPath)); } final Page navRootPage = navRootResource.adaptTo(Page.class); if (null == navRootPage) { throw new IllegalArgumentException(format("Could not get page for navigation root at path %s", navRootPath)); } final Iterable<Page> children = () -> navRootPage.listChildren(); final Stream<Page> navigationStream = StreamSupport.stream(children.spliterator(), false); navigation = navigationStream.filter(navPage -> !navPage.isHideInNav()) .map(navPage -> new Navigation(currentPage, navPage, Long.parseLong(navDepth) - 1)) .collect(Collectors.toList()); } /** * Get the image path for the QR Code. * * @return path to image. */ public final String getQrCodeImage() { return qrCodeImage; } /** * Get property helpCustomerService number. * * @return helpCustomerService number. */ public final String getHelpCustomerService() { return helpCustomerService; } /** * Get helpDeltaAssist handler, twitter handle. * * @return helpDeltaAssist handle. */ public final String getHelpDeltaAssist() { return helpDeltaAssist; } /** * Get reservation office number. * * @return reservation ofc number. */ public final String getHelpReservationOffice() { return helpReservationOffice; } /** * Get logo redirect link. If publish instance return transformed URL. * * @return logo link. */ public final String getLogoLink() { return logoLink; } /** * Get dept/ number of levels for navigation. * * @return nav depth. */ public final String getNavDepth() { return navDepth; } /** * Get root path for the navigation. * * @return root path. */ public final String getNavRootPath() { return navRootPath; } /** * Getter QuickLink. * * @return List of @Link Quicklink. */ public final List<QuickLink> getQuickLinks() { return quickLinks; } /** * Getter alerts. * * @return alerts list. */ public final List<Alert> getAlerts() { return alerts; } /** * Getter Navigation items. * * @return list of navigation items. */ public final List<Navigation> getNavigation() { return navigation; } }
3 Replies

Avatar

Level 1

attached snapshot of the node structure

Avatar

Level 10

IN the Sling Model docs (https://sling.apache.org/documentation/bundles/models.html) - it states: 

Those annotations replace @Via@Filter@Named@Optional@Required@Source and @Inject. Instead of using the deprecated annotation element optional you should rather use injectionStrategy with the values DEFAULTOPTIONAL or REQUIRED (see alsoSLING-4155). @Default may still be used in addition to the injector-specific annotation to set default values. All elements given above are optional.

 

Have you tried what is suggested? 

Avatar

Level 1

Hi Scott,

I did, compilation fails as it cant find the Enum InjectionStrategy.

[ERROR] symbol:   method injectionStrategy()
[ERROR] location: @interface org.apache.sling.models.annotations.injectorspecific.ChildResource
[ERROR] ............../ui/slingmodel/components/global/header/HeaderSlingModel.java:[91,40] cannot find symbol
[ERROR] symbol:   variable InjectionStrategy

This is what I did - 

@ChildResource(injectionStrategy = InjectionStrategy.OPTIONAL)

Its because the InjectionStrategy enum was introduced in Sling Model API v 1.2.0, where as 6.1 SP1 is on v 1.1.0 so we either update the sling model api or use the deprecated option.

Thanks for the help!!