【问题标题】:Apache Felix @Reference annotation problemsApache Felix @Reference 注释问题
【发布时间】:2016-10-23 11:34:24
【问题描述】:

我目前正在开发一个通过 Apache Felix 使用 OSGi 框架的 Sling servlet。据我了解,如果您想获取和使用其他服务,您有两种选择: 1.编写一个服务监听器,确保在获取和使用你的服务之前注册你想要的服务。 2.使用Apache Felix的@Reference注解获取服务。

我想做选项 2,因为选项 1 需要很多我不需要编写的代码。

所以,这就是我的做法。只是一个免责声明:以下是我的代码的 sn-ps,并不构成我的整个项目。不要期望能够编译这个或任何东西。我已经包含了我认为相关的部分。

首先,我有我的 sling servlet:

package mypackage;
import /*necessary imports*/

@Component( name = "My Sling Servlet", immediate = false, metatype = true)
@Properties({
    @Property(name = "sling.servlet.paths", value = "/bin/mytest"),
    @Property(name = "sling.servlet.methods", value = "GET")
})

@Service(Servlet.class)
public class MyServlet extends SlingSafeMethodsServlet {
    @Reference
    private MyService service;

    // Do stuff with service
}

据我了解,@Component 注释让 OSGi 知道这个类文件定义了一个组件。 @Properties 注释定义了组件的一些基本属性(在这种情况下,对我们来说很重要的是,现在我们可以通过转到 [hostname]/bin/mytest 来运行这个 servlet)。 @Service 注释让 OSGi 知道这个类是一个服务(特别是实现了 Servlet 类的服务),并且还注册了这个服务。最后,@Reference 注释告诉 OSGi,我们要声明的字段是这个包中已经注册的 OSGi 服务,我们应该抓住它。

现在,这是另一个相关文件,它定义了服务 MyService:

package mypackage;
import /*necessary imports*/

@Component(name="MyService", immediate=false,metatype=true)

@Service(value = MyServiceInterface.class)
public class MyService implements MyServiceInterface {
    // Implementation of MyServiceInterface
}

在这里,我们使用@Component 注释声明了MyService 是一个OSGi 组件。这里的重要说明是我们使用了@Service 注释,它显然完成了一项基本任务:@Service 注释注册服务。

请假设有一个文件 MyServiceInterface.java 看起来像这样:

package mypackage;
import /*necessary imports*/

public interface MyServiceInterface {
    //stuff
}

在完成所有这些初步准备之后,这是我的问题。当我通过在 Web 浏览器中访问 [hostname]/bin/mytest 来运行我的 servlet 时,我得到一个 404 page not found 错误。这表明我的浏览器找不到 servlet。

您现在可能会问自己为什么我认为这与@Reference 注释有关。好吧,我认为它在某种程度上是负责任的,因为当我将其注释掉并以老式方式(即上面的方法 1)获取服务时,servlet 运行没有任何问题。

另一个可能相关的信息是我正在使用 Maven 来构建这个项目。如果您认为它们会包含有用的信息,我很乐意提供相关的 pom.xml 文件。

请帮我弄清楚为什么我使用@Reference 注解时找不到我的servlet!如果您需要我在帮助我之前提供更多信息,那么我很乐意这样做。如果我没有提供足够的信息,请在 cmets 中指出。

提前致谢!

【问题讨论】:

  • 您是否附加了调试器?您是否实现了#doGet 方法并且正在被访问?
  • 是的,我有一个调试器并且我已经覆盖了doGet 方法。当存在@Reference 注释时,不会达到doGet 方法。但是,当我删除注释时肯定会达到。
  • 如果将 immediate 设置为 true 会发生什么?
  • 安装包时,日志中是否有任何错误?

标签: java servlets osgi apache-felix sling


【解决方案1】:

我总是做的第一件事是检查我的包和 servlet 是否在 Apache Felix 控制台 http://localhost:8080/system/console/bundleshttp://localhost:8080/system/console/components 中处于活动状态。您是否有任何缺失的依赖项阻止您的包或组件激活?

根据您的问题,我的第一个猜测是您可能没有使用Apache Felix Maven SCR Plugin。正如您所说,您不想手动创建 ServiceListeners(您声明的选项 1),而是宁愿使用声明式服务(您声明的选项 2)并且要做到这一点,您需要 SCR 插件。 @Reference 之类的注解不是运行时的,它们被 SCR 插件用来生成您的服务在使用声明式服务的 OSGi 环境中工作所需的代码和元数据。上面提供的文档链接详细介绍了插件的功能。只需将插件添加到您的 pom.xml 文件中,如文档中所示:

<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-scr-plugin</artifactId>
        <version>1.20.0</version>
        <executions>
          <execution>
            <id>generate-scr-scrdescriptor</id>
            <goals>
              <goal>scr</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

Using the Apache Felix Maven SCR Plugin to generate Declarative Services and Metatype Service descriptors during a Maven Build

【讨论】:

  • 感谢您的回复!这些都是需要检查的好东西。至于组件,我已经通过控制台验证它是否处于活动状态。至于 SCR 插件,我确保它包含在我的pom.xml 文件中。尽管如此,我仍然有同样的问题。感谢您的帮助。
【解决方案2】:

如果您的 servlet 在没有引用的情况下工作,并且在您添加引用后它立即停止工作,那么引用本身应该是问题所在。

最明显的解决方案是引用不可访问(无论出于何种原因,可能服务接口类未导出但它在另一个包中?)因此它的状态为“不满意”。在这种情况下,servlet 将无法启动。

你真的检查了 /system/console/components 中的 servlet 还是只检查了相应的组件?

顺便说一句,您的 servlet 不需要所有这些注释。只需使用 @SlingServlet(paths = { "/bin/mytest" }, metatype = false, generateService = true) 然后你可以删除@Component 和@Service。

【讨论】:

    【解决方案3】:

    首先你需要知道是什么原因造成的: 有时您对一个对象使用多个依赖项(特别是在大型项目中),这会导致 IDE 无法识别您的意思。

    就我而言:

        <dependency>
            <groupId>org.onosproject</groupId>
            <artifactId>onos-api</artifactId>
            <version>${onos.version}</version>
        </dependency>
    

    和:

        <dependency>
            <groupId>org.onosproject</groupId>
            <artifactId>onos-providers-openflow-meter</artifactId>
            <version>1.8.9</version>
        </dependency>
    

    两者都指向同一个对象,因此使用 @Reference 注释会导致 IDE 无法注入该对象的问题。 错误的文本可能是这样的:

    Annotation @reference is disallowed for this location.
    

    现在您知道问题所在了,如何解决: 不要使用超出项目需要的依赖项。 在上面的示例中,删除第二个依赖项即可解决问题。

    另一种方法是设置您所指的依赖项: 如您所知,有多种方法可以在 OSGi 注释中使用 @Reference 注释。 而不是使用:

    @Reference
    MyService myService;
    

    使用这个:

    private MyService myService;
    @Reference
    public void bindMyService(MyService myService) {
         this.myService = myService;
    }
    public void unbindMyService(MyService myService) {
         this.myService = myService;
    }
    

    第二个选项解决了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 2015-08-07
      • 2013-12-17
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      相关资源
      最近更新 更多