Phi*_*hil 5 java groovy extension-methods gradle maven-publish
我有一个 groovy 库,我将其作为 jar 文件发布在 Nexus 存储库上。当我使用另一个项目的 Gradle 脚本中的库中的扩展方法时,我收到MissingMethodException。
作为参考,假设我有一个 String 扩展方法,例如:
static boolean containsIgnoreCase(String self, String str) {
self.toLowerCase().contains(str.toLowerCase())
}
Run Code Online (Sandbox Code Playgroud)
如果在我的库中使用调用该方法"foobar".containsIgnoreCase("Foo"),我将得到异常。如果我改为使用 来调用它StringExtensions.containsIgnoreCase("foobar", "Foo"),它就可以工作,没问题。
我的猜测是,这是在没有定义扩展的 META-INF 文件的情况下发布 Groovy 项目的问题。这是项目结构:
- Library
- src/main/
- groovy/
- (here are my sources)
- resources/META-INF/groovy
- org.codehaus.groovy.runtime.ExtensionModule (contains details about my extension classes)
Run Code Online (Sandbox Code Playgroud)
我的 ExtensionModule 文件如下所示:
moduleName=string-extensions
moduleVersion=1.0
extensionClasses=com.my.project.StringExtensions
Run Code Online (Sandbox Code Playgroud)
在build.gradle的发布块中,我使用以下内容:
plugins {
id 'groovy'
id 'java'
id 'maven-publish'
}
//...
sourceSets {
main.groovy.outputDir = sourceSets.main.java.outputDir
test.groovy.outputDir = sourceSets.test.java.outputDir
}
//...
publishing {
publications {
library(MavenPublication) {
from components.java
}
}
//...
}
Run Code Online (Sandbox Code Playgroud)
当我在另一个项目的 Gradle 构建脚本中使用此库时,我需要在出版物中包含哪些内容才能正确注册扩展方法?我已经在构建脚本中添加了依赖项的类路径/存储库 URL,并且可以访问库的方法 - 这些方法在调用扩展方法时会失败。
坏消息:Gradle 中有一个错误,导致 Gradle 构建脚本目前不支持 Groovy 扩展模块。
\n需要注意的一件事: Groovy 文档似乎是错误的,因为他们指定将模块描述符放在META-INF/groovy/. 当我这样做时,我什至可以在普通的 Groovy 应用程序中使用生成的库的扩展方法。我必须把描述符放在下面META-INF/services/才能使其正常工作。
这仍然对 Gradle 用例没有帮助。但是,它表明构建和发布工作正常:FWIW,我自己刚刚设置了两个小项目,我可以重现您所看到的问题(使用 Gradle 6.7.1)。通过提到的目录切换META-INF/services/,我至少可以让扩展在 Groovy 应用程序中工作。因此,鉴于您可以在 Gradle 构建中将 Groovy 方法作为非扩展方法访问,查看问题的其余部分并切换到META-INF/services/,我认为您的构建包括。发布也应该正确配置。
以下两个最小的复制器项目表明该发布有效,该库可以在 Groovy 应用程序中使用,但在 Gradle 构建中失败。Gradle Wrapper 文件未显示。
\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 my_extension_lib\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 groovy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 MyExtension.groovy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 resources\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 META-INF\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 services\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 org.codehaus.groovy.runtime.ExtensionModule\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 my_groovy_app\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 build.gradle\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 groovy\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Test.groovy\nRun Code Online (Sandbox Code Playgroud)\n首先./gradlew publish在my_extension_lib/. 然后跑./gradlew run下my_groovy_app。
my_extension_lib/build.gradle\nplugins {\n id \'groovy\'\n id \'maven-publish\'\n}\n\ngroup = \'com.example\'\nversion = \'1.0\'\n\nrepositories {\n jcenter()\n}\n\ndependencies {\n implementation \'org.codehaus.groovy:groovy-all:2.4.15\'\n}\n\npublishing {\n publications {\n library(MavenPublication) {\n from components.java\n }\n }\n repositories {\n maven {\n name = \'test\'\n url = \'file:///tmp/my_test_repo\'\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n my_extension_lib/src/main/groovy/MyExtension.groovy\nclass MyExtension {\n\n static boolean containsIgnoreCase(String self, String str) {\n self.toLowerCase().contains(str.toLowerCase())\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n my_extension_lib/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule\nplugins {\n id \'groovy\'\n id \'maven-publish\'\n}\n\ngroup = \'com.example\'\nversion = \'1.0\'\n\nrepositories {\n jcenter()\n}\n\ndependencies {\n implementation \'org.codehaus.groovy:groovy-all:2.4.15\'\n}\n\npublishing {\n publications {\n library(MavenPublication) {\n from components.java\n }\n }\n repositories {\n maven {\n name = \'test\'\n url = \'file:///tmp/my_test_repo\'\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n my_groovy_app/build.gradle\n/* Test extension in Gradle */\nbuildscript {\n repositories {\n maven {\n url = \'file:///tmp/my_test_repo\'\n }\n jcenter()\n }\n dependencies {\n classpath \'com.example:my_extension_lib:1.0\'\n }\n}\n\n// works, i.e., the publication is ok\nprintln(MyExtension.containsIgnoreCase("foobar", "Foo"))\n// doesn\xe2\x80\x99t work due to Gradle bug\n//println("foobar".containsIgnoreCase(\'Foo\'))\n\n\n/* Test extension in Groovy application */\n\napply plugin: \'groovy\'\napply plugin: \'application\'\n\napplication {\n mainClass = \'Test\'\n}\n\nrepositories {\n maven {\n url = \'file:///tmp/my_test_repo\'\n }\n jcenter()\n}\n\ndependencies {\n implementation \'org.codehaus.groovy:groovy-all:2.4.15\'\n implementation \'com.example:my_extension_lib:1.0\'\n}\nRun Code Online (Sandbox Code Playgroud)\n my_groovy_app/src/main/groovy/Test.groovy\nclass Test {\n\n static void main(String... args) {\n // works, i.e., extension library JAR was published correctly\n println("foobar".containsIgnoreCase(\'Foo\'))\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1066 次 |
| 最近记录: |