AEM 6.3 || How to call OSGi Service in Sling Model with Service wrote by OSGi R6 Annotation | Community
Skip to main content
New Participant
October 3, 2017
Solved

AEM 6.3 || How to call OSGi Service in Sling Model with Service wrote by OSGi R6 Annotation

  • October 3, 2017
  • 16 replies
  • 46279 views

[Thread Edited By Adobe]

/*Don’t forget to meet and greet your fellow peers virtually by telling them about yourself here

Go ahead and to it now: https://adobe.ly/3eDnB4v */

 

Actual Question:

Dear AEM Community,

 

 

Currently, I'm working on AEM 6.3 OSGi R6 Official OSGi Declarative Services Annotations in AEM - Adobe Experience Manager | AEM/CQ | Apache Sling

But we can't call it in Sling model, we can't use annotation @3214626 (import org.osgi.service.component.annotations.Reference) or @586265 ( from Sling Model) or @586265 @3200416("osgi-services").

 

Any help would be greatly appreciated.

 

Thanks,

Thomas

Best answer by smacdonald2008

THe getSlingScriptHelper().getService();

only works from WCMUsePojo.

I just tested using @inject and it works to inject a running AEM Service into a Sling Model .

Given these classes:

KeyService interface:

package com.community.aem.core;

public interface KeyService {

 

    public void setKey(int val);

    public String getKey();

}

KeyServiceImpl class

package com.community.aem.core;

import org.apache.felix.scr.annotations.Component;

import org.apache.felix.scr.annotations.Service;

//This is a component so it can provide or consume services

@Component

@Service

public class KeyServiceImpl implements KeyService {

  

    //Define a class member named key

    private int key = 0 ;

  

    @Override

    //A basic setter method that sets key

    public void setKey(int val)

    {

        //Set the key class member

        this.key = val ;

       

    }

    @Override

    //A basic getter that gets key

    public String getKey()

    {

        //return the value of the key class member

       

        //Convert the int to a String to display it within an AEM web page

        String strI = Integer.toString(this.key);

        return strI;

    }

}

.

We can inject KeyService into HelloWorldModel - see:

package com.community.aem.core.models;

import javax.annotation.PostConstruct;

import javax.inject.Inject;

import javax.inject.Named;

import com.community.aem.core.KeyService;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.models.annotations.Default;

import org.apache.sling.models.annotations.Model;

import org.apache.sling.settings.SlingSettingsService;

@Model(adaptables=Resource.class)

public class HelloWorldModel {

    @Inject

    private KeyService keyService;

 

    @Inject

    private SlingSettingsService settings;

    @Inject @Named("sling:resourceType") @Default(values="No resourceType")

    protected String resourceType;

    private String message;

    @PostConstruct

    protected void init() {

     

       

        keyService.setKey(80) ;

     

        message = "\tHello World! - the keyservice is " +keyService.getKey() +" \n";

        message += "\tThis is instance: " + settings.getSlingId() + "\n";

        message += "\tResource type is: " + resourceType + "\n";

    }

    public String getMessage() {

        return message;

    }

}

This works -- you can see the successful output here. I hope this clears up how to reference a running AEM Service from WCMUsePojo and Sling models.

You can try this too by following this article to get the default class:

Creating an Adobe Experience Manager 6.3 Project using Adobe Maven Archetype 11

Then add the KeyService and Impl class to the com.community.aem.core package. You will get the same result.  BE  sure to add the new code (bolded code above) to the Sling Model class too!

16 replies

New Participant
October 3, 2017

Hi smacdonald2008​, Feike,

Thanks for your support. After i removed and refresh the bundle it's worked with @Inject annotation.

Thanks,

Thomas.

smacdonald2008
smacdonald2008Accepted solution
New Participant
October 3, 2017

THe getSlingScriptHelper().getService();

only works from WCMUsePojo.

I just tested using @inject and it works to inject a running AEM Service into a Sling Model .

Given these classes:

KeyService interface:

package com.community.aem.core;

public interface KeyService {

 

    public void setKey(int val);

    public String getKey();

}

KeyServiceImpl class

package com.community.aem.core;

import org.apache.felix.scr.annotations.Component;

import org.apache.felix.scr.annotations.Service;

//This is a component so it can provide or consume services

@Component

@Service

public class KeyServiceImpl implements KeyService {

  

    //Define a class member named key

    private int key = 0 ;

  

    @Override

    //A basic setter method that sets key

    public void setKey(int val)

    {

        //Set the key class member

        this.key = val ;

       

    }

    @Override

    //A basic getter that gets key

    public String getKey()

    {

        //return the value of the key class member

       

        //Convert the int to a String to display it within an AEM web page

        String strI = Integer.toString(this.key);

        return strI;

    }

}

.

We can inject KeyService into HelloWorldModel - see:

package com.community.aem.core.models;

import javax.annotation.PostConstruct;

import javax.inject.Inject;

import javax.inject.Named;

import com.community.aem.core.KeyService;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.models.annotations.Default;

import org.apache.sling.models.annotations.Model;

import org.apache.sling.settings.SlingSettingsService;

@Model(adaptables=Resource.class)

public class HelloWorldModel {

    @Inject

    private KeyService keyService;

 

    @Inject

    private SlingSettingsService settings;

    @Inject @Named("sling:resourceType") @Default(values="No resourceType")

    protected String resourceType;

    private String message;

    @PostConstruct

    protected void init() {

     

       

        keyService.setKey(80) ;

     

        message = "\tHello World! - the keyservice is " +keyService.getKey() +" \n";

        message += "\tThis is instance: " + settings.getSlingId() + "\n";

        message += "\tResource type is: " + resourceType + "\n";

    }

    public String getMessage() {

        return message;

    }

}

This works -- you can see the successful output here. I hope this clears up how to reference a running AEM Service from WCMUsePojo and Sling models.

You can try this too by following this article to get the default class:

Creating an Adobe Experience Manager 6.3 Project using Adobe Maven Archetype 11

Then add the KeyService and Impl class to the com.community.aem.core package. You will get the same result.  BE  sure to add the new code (bolded code above) to the Sling Model class too!

smacdonald2008
New Participant
October 3, 2017

Having said that - i have only used this from WCMUsePojo - I have not tried on Sling Model. I will try that and post back.

smacdonald2008
New Participant
October 3, 2017

@Reference does not work in HTL Java classes like Sling Models or WCMUsePojo.

We talk about this in the AEM TIP section: Scott's Digital Community: Adobe Experience Manager FAQs and other Tips

CAN I USE @REFERENCE IN AN HTL CLASS THAT EXTENDS WCMUSEPOJO

You cannot use the @Reference annotation from a HTL class that extends WCMUsePojo. This can be used from a Java class that uses @Service to reference another service known as dependency injection. To learn about Dependency Injection in AEM, see this article:

Injecting a DataSourcePool Service into an Adobe Experience Manager OSGi bundle

Now to learn how to get a referenece to another AEM service from a class that extends WCMUsePojo, see this article:

Creating an AEM HTL component that queries the JCRhttps://helpx.adobe.com/experience-manager/using/htl_jcr.html

Notice we have this code:

//Use getSlingScriptHelper().getService() to get an instance of the CustomerService

        custService = getSlingScriptHelper().getService(CustomerService.class);

New Participant
October 3, 2017

Hi Feike,

Thanks for your support.

Here is the source code

OSGi Services with OSGi R6 Annotation.

import org.apache.commons.lang3.StringUtils;

import org.apache.sling.api.resource.ValueMap;

import org.osgi.service.component.annotations.Component;

import org.osgi.service.component.annotations.Reference;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

@Component(service={ProductSearchService.class}, immediate=true)

public class ProductSearchServiceImpl

  implements ProductSearchService {

// omitted

}

I checked on the OSGi bundle, the services has a status active

Sling Model Class

import javax.annotation.PostConstruct;

import javax.inject.Inject;

import org.apache.sling.api.SlingHttpServletRequest;

import org.apache.sling.api.SlingHttpServletResponse;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.api.resource.ValueMap;

import org.apache.sling.models.annotations.DefaultInjectionStrategy;

import org.apache.sling.models.annotations.Model;

import org.apache.sling.models.annotations.injectorspecific.SlingObject;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

@Model(adaptables={SlingHttpServletRequest.class}, defaultInjectionStrategy=DefaultInjectionStrategy.OPTIONAL)

public class ModelList

{

  private static final Logger LOGGER = LoggerFactory.getLogger(ModelList.class);

  private List<Map<String, Object>> listProperties;

  private List<Integer> pageList;

  private Paging paging;

  @Inject

  protected ProductSearchService searchService;

@PostConstruct

  protected void postInit()

  {

    Resource resource = this.request.getResource();

    ValueMap properties = resource.getValueMap();

    // omited

   result = this.searchService.getListFromParent(resource);

  

}

It's a null when we debugged at this.searchService

Thanks,

Thomas.

Feike_Visser1
Employee
October 3, 2017

Normally @Inject must always work.

Can you share a bit more code?