【问题标题】:Ballerina annotation processing doesn't work as expectedBallerina 注释处理未按预期工作
【发布时间】:2019-12-14 18:28:19
【问题描述】:

我正在尝试使用 ballerina(MacOS Catalina 上的 jBallerina-1.0.5)实现一个简单的注释处理器。在这个例子中,我需要:

  1. 遍历给定service 的可用resource 函数
  2. 对于每次迭代,获取给定@annotation 的值,如resource 中注释的那样

举个例子:

...
service my_service on new http:Listener(8080) {
    @my_annonatation {
        value: "my-value-for-resource-1"
    }
    resource function my_resource_1() {}

    @my_annonatation {
        value: "my-value-for-resource-2"
    }
    resource function my_resource_2() {}
}

根据上面的service代码sn-p,我需要得到resource名称为["my_resource_1", "my_resource_2"]@annotationmy-value-for-resource-1my-value-for-resource-2对应my_resource_1my_resource_2

我的问题是:

  1. 如何使用芭蕾舞演员在给定的service 中定义resources
  2. 我已经尝试使用function getServiceAnnotations(service serviceType, string annotName, string? moduleName = ()) returns anyballerina/reflect 模块来获取@annotation 值。但它没有给出任何回报(显然它返回一个空字符串或可能为空)。

除了旧的 ballerina 0.x pre-releases 1 之外,我没有看到任何关于 ballerina 注释处理的好文章。我发现 ballerina/reflect 模块现在已更新 2 3,因为我与芭蕾舞演员的源代码进行了比较(但在芭蕾舞演员的发布说明 4 中没有提到)。

还有文章“Extending Ballerina”5 提到了另一种通过编译器扩展进行注释处理的方法,该方法将操作委托给 Java。但是,我们将 Java 依赖项推送到 ballerina central 有一个限制。

请建议我一个解决方法以获得预期的结果,非常感谢纯芭蕾舞演员语言的代码。

参考文献

  1. Ballerina Annotation Processing example for 0.9.x releases
  2. ballerina/reflect of 0.x
  3. ballerina/reflect of 1.0.5
  4. Ballerina release notes
  5. Extending Ballerina

【问题讨论】:

  • 请参考这里我们如何读取资源和服务注解,并将注解转换为它的记录类型。然后使用记录的类型可以得到注解github.com/wso2/product-microgateway/blob/jballerina/components/…的值
  • @RajithRoshan 你在现场!,我指的是微网关源代码并在本地成功编译,包括包含注释处理操作的微网关核心。我发现微网关使用不同版本的 Ballerina,ballerina/reflect 模块现已更新。我正在 jballerina-1.0.5 上进行测试。

标签: wso2 annotation-processing ballerina


【解决方案1】:

注释处理可以在编译时或运行时完成。目前(使用 Ballerina 1.0.5 和更早版本),编译时注释处理只能通过“扩展 Ballerina”文档中描述的编译器扩展来完成,而运行时注释访问可以使用 annotation access expression 或通过ballerina/reflect 模块(只有那些无法通过注释访问表达式实现的模块现在在 ballerina/reflect 模块中可用 - 虽然在发行说明中提到了此添加“已引入二进制运算符 .@ 以访问注释值运行时。”,这从 ballerina/reflect 模块中删除了一些功能这一事实似乎被遗漏了)。

https://github.com/ballerina-platform/ballerina-lang/issues/19325 描述了建议的 Ballerina 编译器插件架构,它允许在 Ballerina 中编写扩展。

在运行时:

  1. 检索服务中定义的资源的名称 - IINM 如果不编写外部方法(使用 Java 互操作),目前这是不可能的。编译时不知道资源的名称吗?您可以根据要求创建一个issue in the ballerina-lang repository 吗?

  2. 访问资源注释 - 这可以使用reflect:getResourceAnnotations 方法完成

import ballerina/http;
import ballerina/io;
import ballerina/reflect;

type AnnotRecord record {| 
    string value; 
|};

annotation AnnotRecord my_annonatation on resource function;

string[] resourceNames = ["my_resource_1", "my_resource_2"];

service my_service on new http:Listener(8080) {
    @my_annonatation {
        value: "my-value-for-resource-1"
    }
    resource function my_resource_1(http:Caller caller, http:Request request) {}

    @my_annonatation {
        value: "my-value-for-resource-2"
    }
    resource function my_resource_2(http:Caller caller, http:Request request) {}
}

public function main() {
    foreach var resourceName in resourceNames {
        any annot = reflect:getResourceAnnotations(my_service, resourceName, "my_annonatation");
        if annot is AnnotRecord {
            io:println(annot.value);
        }
    }
}

【讨论】:

  • 感谢您的回复。提交问题以在未来版本中请求资源列表功能是一个好主意。我以完全相同的方式尝试了reflect:getResourceAnnotations 函数。不幸的是,它对我不起作用,它只是给了我一个空值。你能从上面的代码sn-p得到预期的结果吗?您目前使用的是哪个芭蕾舞演员版本?即使是上面的代码,Jballerina-1.0.5 也对我不好。
  • @ChannaJayamuni 我用 1.0.5 试过这个。 ``` $ ballerina -v Ballerina 1.0.5 语言规范 2019R3 ``` 以下是输出 ``` $ ballerina run xyz.bal 编译源 xyz.bal 生成可执行文件 运行可执行文件 my-value-for-resource-1 my -value-for-resource-2 [ballerina/http] 启动 HTTP/WS 监听器 0.0.0.0:8080 ``` 是否有可能共享您正在运行的代码?您还可以确认注释是在同一个文件/模块中还是在不同的文件/模块中定义的?你是否也得到了这个样本的空值?
  • 这很奇怪!它适用于单个芭蕾舞演员文件,但不适用于芭蕾舞演员项目。我在芭蕾舞演员项目中放置了相同的代码,所以我没有得到注释值。您认为这种行为是否有任何具体原因?或者我可能需要在 toml 文件中添加一些配置?
  • 您可以尝试将<org-name>/<module-name>:<version> 作为最后一个参数传递给reflect:getResourceAnnotations 函数吗?例如any annot = reflect:getResourceAnnotations(my_service, resourceName, "my_annonatation", "userone/foo:0.1.0"); 理想情况下,这应该由ballerina/reflect 模块本身处理。我创建了github.com/ballerina-platform/ballerina-lang/issues/20396 来跟踪它。
  • 轰隆隆!!!它像魔术一样工作!谢谢@MaryamZi。我已将 /: 添加到函数中。感谢您为此创建了一个问题。
【解决方案2】:

更新:

@MaryamZis 的解决方案非常适用于单个芭蕾舞演员文件,但不适用于芭蕾舞演员项目。正如她所建议的,我已将<org-name>/<module>:<version> 传递给reflect:getResourceAnnotations 函数的module 参数以使其正常工作。

...
any annot = reflect:getResourceAnnotations(
    my_service, 
    resourceName, 
    "my_annonatation", 
    "my_org/my_module:0.1.0"
);
...

//NOTE: org-name and version are defined in Ballerina.toml of the project

但是,预计在不指定模块的情况下通过reflect 函数检测当前项目的注释。这个issue 由@MaryamZi 记录在ballerina git 存储库中。

【讨论】:

    猜你喜欢
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    相关资源
    最近更新 更多