【问题标题】:OSGi component configurable via Apache FelixOSGi 组件可通过 Apache Felix 进行配置
【发布时间】:2013-03-24 09:16:16
【问题描述】:

我在这方面完全是新手,所以我提前道歉。我正在尝试创建 一个 OSGi 组件,它简单地显示一个 hello world 消息,并且可以通过 felix 的输入进行配置。然后在一个jsp页面上吐出来。我正在使用 scr 注释来帮助做到这一点。这是我的java代码

package com.training.cq5.trainingApp;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.service.component.ComponentContext;
import org.apache.sling.commons.osgi.PropertiesUtil;

@Component(label= "Welcome Message",
        description = "Welcome Message for the training excercise",
        immediate = true, enabled = true, metatype=true)
@Properties({
    @Property(name = "welcome.message", value = "WelcomeMessage")
})
@Service(WelcomeMessage.class)
public class WelcomeMessage {

    private static String welcome_message = "Welcome";

    @Activate
    protected void activate(ComponentContext ctx) {
        welcome_message = PropertiesUtil.toString(ctx.getProperties().get(welcome_message), welcome_message);
    }

    public static String getMessage() { 
        return welcome_message;
    }
}

这是我在 JSP 中调用它:

<%@ page import="com.training.cq5.trainingApp.WelcomeMessage" %>

<h2><%= WelcomeMessage.getMessage() %></h2>

它没有从 felix 更新有什么原因吗?我得到的只是“欢迎” welcome_message 字符串中的文本。

【问题讨论】:

    标签: java maven osgi apache-felix sling


    【解决方案1】:

    您正在以静态方法访问 WelcomeMessage.getMessage(),但您想要的是实际服务。当您使用@Service 和@Component 注释来注释一个类时,您向OSGI 框架表明您希望将此类的实例注册为服务。此服务实例由 OSGI 框架管理,根据其生命周期(实例化时)或通过哪个类加载器加载适当的类。

    但是,为了使用@Component 和@Service 注释,您必须使用Apache Felix SCR plugin。一旦成功,您的服务将被实例化。

    然后您必须访问该服务。您似乎正在使用的 Sling 中最简单的方法是 SlingScriptHelper.getService(),它可以让您查找服务。

    更新

    在 OSGI 中,服务是按其类型注册的。当您使用@Service(MyClass.class) 声明服务时,该服务将注册到 MyClass 类型下。要检索它,您将在服务注册表中查询给定类型的服务。在 Java 代码中,您将使用 getServiceReference(Class clazz)/getService(ServiceReference reference)@Reference 注释。

    在 Sling 系统上的 JSP 中,您可以使用 SlingScriptHelper,如前所述。这是一个简短的代码示例(假设导入正确):

    <%
    SlingBindings bindings = (SlingBindings) req.getAttribute(SlingBindings.class.getName());
    SlingScriptHelper scriptHelper = bindings.getSling();
    MyService service = scriptHelper.getService(MyService.class);
    // ... do stuff with service.
    %>
    

    如果您打算更多地使用 OSGI,我强烈推荐OSGI specification。它可以免费下载并详细解释所有内容。

    【讨论】:

    • 谢谢@ilikeorangutans。我确实安装并运行了 Apache Felix SCR 插件。那么我的问题只是在于通过吊索访问它?对不起,我是一个完整的,我的意思是完整的新手。对我的代码的任何修改将不胜感激。或者任何代码示例都会有很大帮助。谢谢!
    • 谢谢@ilikeorangutans。知道为什么我在添加您的 JSP 时会收到此错误。 SlingBindings 无法解析为类型
    • 您在页面中缺少适当的导入:
    • 感谢@ilikeorangutans,但由于某种原因,现在我遇到了另一个错误重复的局部变量绑定有什么想法吗?感谢您的帮助,我对此很陌生,仍在学习
    • 这意味着已经定义了绑定。您可能可以跳过第一行。
    【解决方案2】:

    ilikeorangutans 是正确的,您不希望在 OSGi 服务上使用静态方法 - 想法是服务实现一个接口,客户端从其 OSGi 上下文中检索它并通过其服务接口使用它。

    Apache Sling webloader sample 使用此技术在其请求处理脚本中访问 Webloader 服务。在这种情况下,脚本是 ESP(服务器端 javascript),但原理与 JSP 完全相同。

    服务接口在Webloader.java中定义,WebLoaderImpl.java将其实现为OSGi服务。

    然后,html.esp 脚本使用 sling.getService 获取服务:

    var loader = sling.getService(Packages.org.apache.sling.samples.webloader.Webloader);
    

    【讨论】:

    • 谢谢@bertrand!这个概念是有道理的,但我有点困惑。我在 webloader 示例中没有看到 esp 脚本。但在 esp 中,我假设您使用 sling.getService 然后在我的情况下调用 loader.getMessage() 。抱歉,这里有点新手,我必须在我的 jsp 文件中做所有事情才能让它工作,或者我的 java 代码是否需要一些修改。对我的代码的任何修改将不胜感激。感谢您的帮助!
    • 与此同时,我在svn.apache.org/repos/asf/sling/trunk/launchpad/… 的 Sling 测试脚本中找到了一个示例 - 您可以查看它如何使用 ConfigurationAdmin 服务并使用您的 WelcomeService 执行类似的操作。您需要创建一个描述该服务契约的 java 接口,并像我之前提到的 Webloader 和 WebLoaderImpl 一样创建一个实现。
    【解决方案3】:

    改变这一行:- welcome_message = PropertiesUtil.toString(ctx.getProperties().get(welcome_message), welcome_message);

    welcome_message = PropertiesUtil.toString(ctx.getProperties().get("welcome.message"), welcome_message);

    注意区别:-ctx.getProperties().get(welcome_message) 与 ctx.getProperties().get("welcome.message")

    【讨论】: