[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 S...
But we can't call it in Sling model, we can't use annotation @reference (import org.osgi.service.component.annotations.Reference) or @inject ( from Sling Model) or @inject @source("osgi-services").
Any help would be greatly appreciated.
Thanks,
Thomas
Solved! Go to Solution.
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!
Normally @Inject must always work.
Can you share a bit more code?
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.
@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
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
);
Views
Replies
Total Likes
Having said that - i have only used this from WCMUsePojo - I have not tried on Sling Model. I will try that and post back.
Views
Replies
Total Likes
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!
Hi smacdonald2008, Feike,
Thanks for your support. After i removed and refresh the bundle it's worked with @Inject annotation.
Thanks,
Thomas.
I am glad that its working for you. I also added this to our AEM tip blog.
Views
Replies
Total Likes
if i don't define the interface can't we inject the services.
As one of my service don't have any interface . initially it is not working and only working when i added a interface to it.
But it is existing code, i should not change that code
Services should always have an interface to Implement .
Hi Scot,
Even i am facing the same problem. OSGi services injected in a sling model is null.
Service is active, i even deleted and re-deployed bundle but it does not work. Same service when invoked from WCMUsePojo with the help of getSlingScriptHelper().getService(
); works.
Can you please help me what can be done to fix this issue.
Even @Inject of SlingSettingsService is null.
Thanks & Regards,
Srikanth
is your Sling Model getting Injected properly ?
Hi Veena,
Sling model is injected correctly. I was able to resolve by using annotation @OSGiService instead of @inject for service invocation to work in AEM 6.4.
Thanks for the response.
Thanks & Regards,
Srikanth
Can anyone explain why? Why do we have to have a interface for every service?smacdonald2008
As you are aware that we work with OSGI Services. So the basic documentations says "An OSGi service is a java object instance, registered into an OSGi framework with a set of properties. Any java object can be registered as a service, but typically it implements a well-known interface."
Some references that might help you https://www.osgi.org/developer/architecture/
https://www.osgi.org/developer/architecture/
I tried both @OSGiService and @Inject to call service in Sling model. It's Not working in both cases.
I am using AEM 6.4 with SP6.4.5
i am getting this error:
Caused by: org.apache.sling.scripting.sightly.SightlyException: Identifier com.arya.mypackage.core.models.HelloWorldModel cannot be correctly instantiated by the Use API
at org.apache.sling.scripting.sightly.impl.engine.extension.use.UseRuntimeExtension.call(UseRuntimeExtension.java:78) [org.apache.sling.scripting.sightly:1.0.48.1_3_1]
at org.apache.sling.scripting.sightly.impl.engine.runtime.RenderContextImpl.call(RenderContextImpl.java:69) [org.apache.sling.scripting.sightly:1.0.48.1_3_1]
at org.apache.sling.scripting.sightly.apps.aryaproject.components.content.helloworld.helloworld_html.render(helloworld_html.java:55)
at org.apache.sling.scripting.sightly.java.compiler.RenderUnit.render(RenderUnit.java:48) [org.apache.sling.scripting.sightly.compiler.java:1.0.22.1_3_1]
at org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript.eval(SightlyCompiledScript.java:61) [org.apache.sling.scripting.sightly:1.0.48.1_3_1]
at org.apache.sling.scripting.core.impl.DefaultSlingScript.call(DefaultSlingScript.java:386) [org.apache.sling.scripting.core:2.0.54]
at org.apache.sling.scripting.core.impl.DefaultSlingScript.eval(DefaultSlingScript.java:184) [org.apache.sling.scripting.core:2.0.54]
at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:491) [org.apache.sling.scripting.core:2.0.54]
... 250 common frames omitted
Caused by: org.apache.sling.models.factory.MissingElementsException: Could not inject all required fields into class com.arya.mypackage.core.models.HelloWorldModel
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:679) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
at org.apache.sling.models.impl.ModelAdapterFactory.internalCreateModel(ModelAdapterFactory.java:394) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
at org.apache.sling.models.impl.ModelAdapterFactory.createModel(ModelAdapterFactory.java:261) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
at org.apache.sling.scripting.sightly.models.impl.SlingModelsUseProvider.provide(SlingModelsUseProvider.java:135) [org.apache.sling.scripting.sightly.models.provider:1.0.6]
at org.apache.sling.scripting.sightly.impl.engine.extension.use.UseRuntimeExtension.call(UseRuntimeExtension.java:73) [org.apache.sling.scripting.sightly:1.0.48.1_3_1]
... 257 common frames omitted
Suppressed: org.apache.sling.models.factory.MissingElementException: Could not inject private com.arya.mypackage.core.interfaces.KeyService com.arya.mypackage.core.models.HelloWorldModel.keyService
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:684) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
... 261 common frames omitted
Caused by: org.apache.sling.models.factory.ModelClassException: No injector returned a non-null value!
at org.apache.sling.models.impl.ModelAdapterFactory.injectElement(ModelAdapterFactory.java:581) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:682) [org.apache.sling.models.impl:1.4.7.T20180205124646-b0647a3]
... 261 common frames omitted
Hi,
Can you check if your sling model is adaptable to both resource and SlingHttpServletRequest i.e. @Model(adaptables = { Resource.class, SlingHttpServletRequest.class })
Views
Likes
Replies