首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Apache @Reference注释问题

Apache @Reference注释问题
EN

Stack Overflow用户
提问于 2016-06-21 19:01:17
回答 3查看 2.8K关注 0票数 1

我目前正在开发一个Sling servlet,它通过Apache使用OSGi框架。据我所知,如果您想获得和使用另一个服务,您有两个选项: 1.编写一个服务侦听器,确保在获取和使用您的服务之前注册您想要的服务。2.使用Apache的@Reference注释获取服务。

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

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

首先,我有了吊索servlet:

代码语言:javascript
复制
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:

代码语言:javascript
复制
package mypackage;
import /*necessary imports*/

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

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

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

请假设有一个类似于以下内容的文件MyServiceInterface.java:

代码语言:javascript
复制
package mypackage;
import /*necessary imports*/

public interface MyServiceInterface {
    //stuff
}

在所有这些准备工作中,这是我的问题。当我在web浏览器中访问[hostname]/bin/mytest运行servlet时,我会得到一个404页未找到的错误。这表明我的浏览器找不到servlet。

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

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

请帮助我弄清楚为什么当我使用@Reference注释时无法找到我的servlet!如果你需要我在帮助我之前提供更多的信息,那么我很乐意这样做。如果我没有提供足够的资料,请在评论中注明。

提前谢谢!

EN

回答 3

Stack Overflow用户

发布于 2016-06-23 02:08:18

我总是做的第一件事是检查我的包和servlet是否在http://localhost:8080/system/console/bundleshttp://localhost:8080/system/console/components的Apache控制台中活动。您是否有任何缺失的依赖关系来阻止您的包或组件变得活跃?

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

代码语言:javascript
复制
<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>

使用Apache插件在Maven构建期间生成声明性服务和元类型服务描述符

票数 0
EN

Stack Overflow用户

发布于 2016-06-28 10:06:39

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

最明显的解决方案是,引用是不可访问的(无论出于什么原因,服务接口类可能不是导出的,而是在另一个包中?)因此,它具有“不满意”的地位。在这种情况下,servlet将不会启动。

您真的在/system/控制台/组件中签入了servlet,还是只检查了相应的组件?

顺便说一下,servlet不需要所有这些注释。只需使用@SlingServlet(path={ "/bin/mytest“}、metatype = false、generateService = true),就可以删除@组件和@Service。

票数 0
EN

Stack Overflow用户

发布于 2019-07-14 05:36:28

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

就我而言:

代码语言:javascript
复制
    <dependency>
        <groupId>org.onosproject</groupId>
        <artifactId>onos-api</artifactId>
        <version>${onos.version}</version>
    </dependency>

以及:

代码语言:javascript
复制
    <dependency>
        <groupId>org.onosproject</groupId>
        <artifactId>onos-providers-openflow-meter</artifactId>
        <version>1.8.9</version>
    </dependency>

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

代码语言:javascript
复制
Annotation @reference is disallowed for this location.

现在您已经知道了问题所在,如何解决这个问题:不要比项目需要更多地使用依赖关系。在上面的例子中,删除第二个依赖解决了这个问题。

另一种方法是设置确切的依赖关系:如您所知,在OSGi注释中使用@Reference注释有多种方法。而不是使用:

代码语言:javascript
复制
@Reference
MyService myService;

用这个:

代码语言:javascript
复制
private MyService myService;
@Reference
public void bindMyService(MyService myService) {
     this.myService = myService;
}
public void unbindMyService(MyService myService) {
     this.myService = myService;
}

第二种选择解决了问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37952560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档