Expand my Community achievements bar.

SOLVED

unsatisfied service

Avatar

Former Community Member

Hi,

The below is my customised servlet :

@SuppressWarnings("serial")

@SlingServlet(paths="/services/trialServlet",methods="GET")

public class trialServlet extends SlingAllMethodsServlet {

  @Reference Name1 varname;

  @Override

  protected void doGet(SlingHttpServletRequest request,SlingHttpServletResponse response)throws ServletException,IOException

  {

  String test;

  test=request.getParameter("name");

  try {

  response.getWriter().write("test");

  } catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  @Override

  protected void doPost(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException

  {

  varname.setName("teju");

  String n=varname.getName();

  response.getWriter().write(n);

  /*String test;

  test=request.getParameter("name");*/

  try {

  response.getWriter().write(n);

  } catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

When I'm checking in the bundle, I'm getting Component #2994 com.myTectra.workflowstep.trialServlet, state unsatisfied (reference).

Please let me know why this is happening and what is the solution for it.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi Pooja

     @reference should be used to refer a service. If any @reference annotation is not able to pick the correct service , bundle will throw unsatisfied service error. Please check if Name1 is properly initialized as a service and is available in the Felix console as a service. Let me know if you need any more information around this .

Thanks

Veena

View solution in original post

8 Replies

Avatar

Level 10

Hi,

May I know which service you are trying to inject to.

Like in your code I see  @Reference Name1 varname;

~Ratna.

Avatar

Level 10

Looks like you are trying to inject a data type that does not exist in the OSGi Service layer. You have to ensure that any service you inject - it must be available.

Avatar

Correct answer by
Community Advisor

Hi Pooja

     @reference should be used to refer a service. If any @reference annotation is not able to pick the correct service , bundle will throw unsatisfied service error. Please check if Name1 is properly initialized as a service and is available in the Felix console as a service. Let me know if you need any more information around this .

Thanks

Veena

Avatar

Former Community Member

I'm using @Reference to inject the service Name1. Here's the interface Name1:

public interface Name1 {

  String getName();

  void setName(String name);

}

Please let me know if this initialisation is right.

Avatar

Level 10

You cannot do that!

In OSGi, an interface is used to create a custom Service that has an implementation class.

See this Article - a very basic example --

Scott's Digital Community: Creating your first AEM Service using an Adobe Maven Archetype project

For example - we have an interface named  keyService

public interface KeyService {

   

    public void setKey(int val);

    public String getKey();

}

Then we have an implementation class named KeyServiceImpl that uses @Component and @Service:

import com.adobe.cq.KeyService;

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;

    }

}

Now we have a custom service in AEM named keyService (when the OSGi bundle is deployed and in an Active State).

You can inject this keyService into another AEM service using @Reference. (note that if you are using HTL WCMUSEPOJO - you cannot use @REference)

For example - assume we have keyService2

public interface KeyService2 {

   

    public void setKey(int val);

    public String getKey();

}

The following example shows an implementation class that injects KeyService into it using @Reference.

import com.adobe.cq.KeyService2; // implem interface

import com.adobe.cq.KeyService; //used for dep inject

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

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

@Reference

public KeyService myKey

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

@Component

@Service

public class KeyServiceImpl2 implements KeyService2 {

   

    //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;

    }

}

This is how dependency injection works in AEM. You can only inject an all ready running service using @Reference.

See this article -  we inject a DataSourcePool Service into a custom service to work with a relational database.

Scott's Digital Community: Injecting a DataSourcePool Service into an Adobe Experience Manager OSGi ...

Hope this clears up how to use dependency injection in AEM.

Avatar

Community Advisor

Please write a service which implements this interface as scott has explained below and then you can use the same snippet you wer using to refer the service,

Avatar

Former Community Member

I have written an implementation class as below:

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

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

@Component(metatype=true)

@Service

public class Name1Impl implements Name1 {

  String name;

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name=name;

  }

}

And changed my existing class according:

public class trialServlet extends SlingAllMethodsServlet {

  @Reference Name1Impl varname;

  @Override

  protected void doGet(SlingHttpServletRequest request,SlingHttpServletResponse response)throws ServletException,IOException

  {

  String test;

  test=request.getParameter("name");

  try {

  response.getWriter().write("test");

  } catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  @Override

  protected void doPost(SlingHttpServletRequest request,SlingHttpServletResponse response) throws ServletException,IOException

  {

  varname.setName("teju");

  String n=varname.getName();

  response.getWriter().write(n);

  /*String test;

  test=request.getParameter("name");*/

  try {

  response.getWriter().write(n);

  } catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

Now I see that in the console:

Component #3022 com.myTectra.serviceImpl.Name1Impl, state satisfied

and my class still unsatisfied.

Avatar

Employee Advisor

You should reference the service interface, not the service implementation.

@Reference Name1 varname;

Jörg