我目前正在开发一个Sling servlet,它通过Apache Felix使用OSGi框架。据我所知,如果您想获得并使用其他服务,您有两种选择:
1.编写服务监听器,确保在获取和使用服务之前注册所需的服务。
2.使用Apache Felix的@Reference
注释获取服务。
我想做选项2,因为选项1需要大量我不需要编写的代码。
所以,这就是我如何做到的。只是一个免责声明:以下是我的代码的片段,并不构成我的整个项目。不要指望能够编译这个或任何东西。我已经包含了我认为相关的部分。
首先,我有我的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
}
在这里,我们声明MyService是一个使用@Component
注释的OSGi组件。这里的重要注意事项是我们使用@Service
注释,它显然完成了一项基本任务: @Service
注释注册服务。
请假设有一个MyServiceInterface.java文件,如下所示:
package mypackage;
import /*necessary imports*/
public interface MyServiceInterface {
//stuff
}
随着所有这些预备工作的完成,这是我的问题。当我通过在Web浏览器中访问[hostname]/bin/mytest
来运行我的servlet时,我得到404页面未找到错误。这表明我的浏览器找不到servlet。
您现在可能会问自己为什么我认为这与@Reference
注释有某种关联。嗯,我认为它有点负责任,因为当我发表评论并以旧式方式(即上面的方法1)获得服务时,servlet运行没有任何问题。
另一个可能相关的信息是我正在使用Maven来构建这个项目。如果您认为它们包含有用信息,我很乐意提供相关的pom.xml文件。
请帮助我弄清楚当我使用@Reference
注释时无法找到我的servlet的原因!如果您在帮助我之前需要我提供更多信息,那么我很乐意这样做。如果我没有提供足够的信息,请在评论中注明。
提前致谢!
答案 0 :(得分:0)
我经常做的第一件事是检查我的bundle和servlet是否在http://localhost:8080/system/console/bundles和http://localhost:8080/system/console/components的Apache Felix控制台中处于活动状态。您是否有任何遗漏的依赖项阻止您的捆绑或组件变为活动状态?
根据您的问题,我的第一个猜测是您可能没有使用Apache Felix Maven SCR Plugin。如你所说,你不想手动创建ServiceListeners(你声明的选项1),而是宁愿使用Declarative Services(你声明的选项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>
答案 1 :(得分:0)
如果您的servlet在没有引用的情况下工作,并且在添加引用后它立即停止工作,那么引用本身就应该是问题。
最明显的解决方案是无法访问引用(无论出于何种原因,可能是服务接口类未导出但是它在另一个包中?)因此它的状态为“notisfied”。在这种情况下,servlet无法启动。
您是否确实在/ system / console / components中检查了servlet,或者您是否只检查了相应的组件?
BTW您的servlet不需要所有这些注释。简单地使用 @SlingServlet(paths = {“/ bin / mytest”},metatype = false,generateService = true) 您可以删除@Component和@Service。
答案 2 :(得分:0)
首先,您需要知道是什么原因造成的: 有时,您对一个对象(尤其是在大型项目中)使用多个依赖关系,这将导致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;
}
第二个选项解决了这个问题。