Groovy 打包到 Jar 中无法使用 Maven。原因:java.lang.AbstractMethodError
Groovy packaged into a Jar not working using maven. Caused by: java.lang.AbstractMethodError
所以我有一个 groovy 包集合,我已经使用 mvn package 成功地将它们打包成一个 jar 文件。
我成功地将这个 jar 文件添加到另一个编译正常的项目中,但是当尝试实际使用该 jar 时,我收到以下错误。
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.AbstractMethodError: pefservices.restapi.Request.getProperty(Ljava/lang/String;)Ljava/lang/Object;
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Request.ViewPoint(Request.groovy:185)
at pefservices.restapi.Request.ViewPoint(Request.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Client.profile(Client.groovy:59)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Client.getName(Client.groovy:20)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.viewpoint.Client.<init>(Client.groovy:30)
at pefservices.viewpoint.Client.<init>(Client.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.viewpoint.User.<init>(User.groovy:35)
at pefservices.viewpoint.User.<init>(User.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.setup.Session.enableFramework(Session.groovy:188)
at pefservices.setup.Session.enableFramework(Session.groovy)
at pefservices.setup.Session$enableFramework.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
at main.App.main(App.groovy:15)
Caused by: java.lang.AbstractMethodError:
pefservices.restapi.Request.getProperty(Ljava/lang/String;)Ljava/lang/Object;
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:190)
at groovy.lang.Closure.getPropertyTryThese(Closure.java:313)
at groovy.lang.Closure.getPropertyOwnerFirst(Closure.java:307)
at groovy.lang.Closure.getProperty(Closure.java:296)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Request$_ViewPoint_closure1.doCall(Request.groovy:182)
at pefservices.restapi.Request$_ViewPoint_closure1.doCall(Request.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
at groovy.lang.Closure.call(Closure.java:405)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:122)
at com.sun.proxy.$Proxy7.get(Unknown Source)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
下面是它失败的 class,它似乎在它试图访问 class 属性 时发生(我已经尝试从这个特定的 class 它工作得很好,但在另一个 class 上失败了,它得到另一个 属性)
import java.nio.CharBuffer
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import groovy.json.JsonOutput
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request as Req
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.OkHttpClient.Builder as ClientBuilder
import okhttp3.Request.Builder
import okio.Buffer
import pefservices.restapi.User as UserAPI
import pefservices.setup.*
public class Request {
Map <String, String> cache = new HashMap <String, String>()
Map <String, CompletableFuture <?>> inProcess = new HashMap <String, CompletableFuture <?>>()
//includes Authorization
public def ViewPoint(String url, String RequestMethod, def requestBody='', Map headers=[:], boolean asAdmin=true, def asUser=null) {
if(!url.startsWith("http://"))
{
url='http://'+url
}
String toBeCached = url+RequestMethod+requestBody+headers+Values+asAdmin+asUser
waitForRequestifExists(toBeCached)
if(!cache.containsKey(toBeCached))
{
def inputLine
inProcess.put(toBeCached, new CompletableFuture().supplyAsync(
{
OkHttpClient client = new ClientBuilder().connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS).build();
println "restAPI [$RequestMethod] URL: "+url
Builder builder =new Builder().url(url)
// headers+=["Accept-Encoding" :"gzip, deflate"]
headers+=["Accept" :"application/json, text/plain, */*"]
headers+=["Accept-Language" :"en-US,en;q=0.5"]
headers+=["Expires" :"-1"]
headers+=["Connection" :"keep-alive"]
if(requestBody instanceof File)
{
String boundary = "-------------" + System.currentTimeMillis();
headers+=['Content-Type':'multipart/form-data; boundary='+boundary]
}
if(!headers.containsKey("Content-Type"))
{
headers+=["Content-Type" :"application/json; charset=UTF-8; odata.metadata=minimal"]
}
if (!url.contains("api/open") && url.contains(Session.url))
{
if (asAdmin==true)
{
headers+=["Authorization" :Session.tokens['adminToken']];
}
else if(asUser!=null)
{
UserAPI userAPI = new UserAPI();
headers+=["Authorization" :userAPI.loginPost(asUser).Token]
}
else{
headers+=["Authorization" :Session.tokens['userToken']];
}
}
for(entry in headers) {
builder.addHeader(entry.key, entry.value)
}
if (!(requestBody instanceof String) && headers['Content-Type'].toString().contains("json"))
{
requestBody = JsonOutput.toJson(requestBody)
}
if (RequestMethod != 'GET')
{
try{
println "Json body:->"+ JsonOutput.prettyPrint(requestBody)
}
catch (Throwable ex)
{
println "body:"+ requestBody
}
if(requestBody instanceof File)
{
RequestBody body = RequestBody.create(MediaType.parse(headers['Content-Type']), requestBody)
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", requestBody.getName(), body)
.build()
builder.method(RequestMethod, formBody)
}
else{
RequestBody body = RequestBody.create(MediaType.parse(headers['Content-Type']), requestBody)
builder.method(RequestMethod, body)
}
}
Req request = builder.build()
Response response = client.newCall(request).execute()
int responseCode = response.code()
String responseTitle = response.message()
if(response.header("Content-Disposition")?.contains('attachment'))
{
String header =response.header("Content-Disposition")
String fileExtension = header.substring(header.lastIndexOf('.'))
println "Content-Disposition: attachment - File Extension ->$fileExtension"
File file = new File(".\TestFiles\temp$fileExtension")
InputStream IS= response.body().byteStream()
BufferedInputStream input = new BufferedInputStream(IS);
OutputStream output = new FileOutputStream(file);
byte[] data = new byte[1024];
long total = 0
int count
while ((count =input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
inputLine = file
}
else
{
inputLine = response.body().string()
}
println "RESTAPI Response Code: -> "+ responseCode
if (responseCode >= 400)
{
println "Message: -> " + responseTitle
println "Error Resposne body: -> "+inputLine
throw new Exception("Error Code =$responseCode URL: $url")
}
具体在以下行中失败
cache[toBeCached] = inputLine
}, new Executors().newSingleThreadExecutor()))
inProcess[toBeCached].get(120, TimeUnit.SECONDS)
inProcess.remove(toBeCached)
if(RequestMethod == "POST")
{println "restapi.Request() ->"+inputLine
}
return inputLine
}
else
{
return cache.get(toBeCached)
}
}
public void waitForRequestifExists(String key)
{
if(inProcess.containsKey(key))
{
this.inProcess[key].get(120, TimeUnit.SECONDS)
}
}
public void clearCache()
{
this.cache = new HashMap <String, String>()
this.inProcess = new HashMap <String, CompletableFuture <?>>()
}
}
我遇到了类似的问题,结果是用于编译 groovy 代码的 maven 插件有一些问题。我使用 this answer.
解决了它
基本上您需要明确指定 groovy-eclipse-compiler
和 groovy-eclipse-batch
的版本。在我的 POM 中,我将 metaversion 值设置为 LATEST
。相反,请尝试使用 <version>3.6.0-03</version>
等具体值。 (之后尝试清除您的 .m2 存储库缓存。)
如果您在构建过程中使用这些插件,则适用。
我在我们的 maven 项目中看到了 AbstractMethodError。似乎问题在于 groovy-all 和 groovy-eclipse-batch 的版本应该匹配。 eric-milles 在 groovy-eclipse issue 中的评论很有帮助。
所以我有一个 groovy 包集合,我已经使用 mvn package 成功地将它们打包成一个 jar 文件。
我成功地将这个 jar 文件添加到另一个编译正常的项目中,但是当尝试实际使用该 jar 时,我收到以下错误。
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.AbstractMethodError: pefservices.restapi.Request.getProperty(Ljava/lang/String;)Ljava/lang/Object;
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Request.ViewPoint(Request.groovy:185)
at pefservices.restapi.Request.ViewPoint(Request.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Client.profile(Client.groovy:59)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Client.getName(Client.groovy:20)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.viewpoint.Client.<init>(Client.groovy:30)
at pefservices.viewpoint.Client.<init>(Client.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.viewpoint.User.<init>(User.groovy:35)
at pefservices.viewpoint.User.<init>(User.groovy)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.setup.Session.enableFramework(Session.groovy:188)
at pefservices.setup.Session.enableFramework(Session.groovy)
at pefservices.setup.Session$enableFramework.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
at main.App.main(App.groovy:15)
Caused by: java.lang.AbstractMethodError:
pefservices.restapi.Request.getProperty(Ljava/lang/String;)Ljava/lang/Object;
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:190)
at groovy.lang.Closure.getPropertyTryThese(Closure.java:313)
at groovy.lang.Closure.getPropertyOwnerFirst(Closure.java:307)
at groovy.lang.Closure.getProperty(Closure.java:296)
at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:234)
at pefservices.restapi.Request$_ViewPoint_closure1.doCall(Request.groovy:182)
at pefservices.restapi.Request$_ViewPoint_closure1.doCall(Request.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
at groovy.lang.Closure.call(Closure.java:405)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:122)
at com.sun.proxy.$Proxy7.get(Unknown Source)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
下面是它失败的 class,它似乎在它试图访问 class 属性 时发生(我已经尝试从这个特定的 class 它工作得很好,但在另一个 class 上失败了,它得到另一个 属性)
import java.nio.CharBuffer
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import groovy.json.JsonOutput
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request as Req
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.OkHttpClient.Builder as ClientBuilder
import okhttp3.Request.Builder
import okio.Buffer
import pefservices.restapi.User as UserAPI
import pefservices.setup.*
public class Request {
Map <String, String> cache = new HashMap <String, String>()
Map <String, CompletableFuture <?>> inProcess = new HashMap <String, CompletableFuture <?>>()
//includes Authorization
public def ViewPoint(String url, String RequestMethod, def requestBody='', Map headers=[:], boolean asAdmin=true, def asUser=null) {
if(!url.startsWith("http://"))
{
url='http://'+url
}
String toBeCached = url+RequestMethod+requestBody+headers+Values+asAdmin+asUser
waitForRequestifExists(toBeCached)
if(!cache.containsKey(toBeCached))
{
def inputLine
inProcess.put(toBeCached, new CompletableFuture().supplyAsync(
{
OkHttpClient client = new ClientBuilder().connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS).build();
println "restAPI [$RequestMethod] URL: "+url
Builder builder =new Builder().url(url)
// headers+=["Accept-Encoding" :"gzip, deflate"]
headers+=["Accept" :"application/json, text/plain, */*"]
headers+=["Accept-Language" :"en-US,en;q=0.5"]
headers+=["Expires" :"-1"]
headers+=["Connection" :"keep-alive"]
if(requestBody instanceof File)
{
String boundary = "-------------" + System.currentTimeMillis();
headers+=['Content-Type':'multipart/form-data; boundary='+boundary]
}
if(!headers.containsKey("Content-Type"))
{
headers+=["Content-Type" :"application/json; charset=UTF-8; odata.metadata=minimal"]
}
if (!url.contains("api/open") && url.contains(Session.url))
{
if (asAdmin==true)
{
headers+=["Authorization" :Session.tokens['adminToken']];
}
else if(asUser!=null)
{
UserAPI userAPI = new UserAPI();
headers+=["Authorization" :userAPI.loginPost(asUser).Token]
}
else{
headers+=["Authorization" :Session.tokens['userToken']];
}
}
for(entry in headers) {
builder.addHeader(entry.key, entry.value)
}
if (!(requestBody instanceof String) && headers['Content-Type'].toString().contains("json"))
{
requestBody = JsonOutput.toJson(requestBody)
}
if (RequestMethod != 'GET')
{
try{
println "Json body:->"+ JsonOutput.prettyPrint(requestBody)
}
catch (Throwable ex)
{
println "body:"+ requestBody
}
if(requestBody instanceof File)
{
RequestBody body = RequestBody.create(MediaType.parse(headers['Content-Type']), requestBody)
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", requestBody.getName(), body)
.build()
builder.method(RequestMethod, formBody)
}
else{
RequestBody body = RequestBody.create(MediaType.parse(headers['Content-Type']), requestBody)
builder.method(RequestMethod, body)
}
}
Req request = builder.build()
Response response = client.newCall(request).execute()
int responseCode = response.code()
String responseTitle = response.message()
if(response.header("Content-Disposition")?.contains('attachment'))
{
String header =response.header("Content-Disposition")
String fileExtension = header.substring(header.lastIndexOf('.'))
println "Content-Disposition: attachment - File Extension ->$fileExtension"
File file = new File(".\TestFiles\temp$fileExtension")
InputStream IS= response.body().byteStream()
BufferedInputStream input = new BufferedInputStream(IS);
OutputStream output = new FileOutputStream(file);
byte[] data = new byte[1024];
long total = 0
int count
while ((count =input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
inputLine = file
}
else
{
inputLine = response.body().string()
}
println "RESTAPI Response Code: -> "+ responseCode
if (responseCode >= 400)
{
println "Message: -> " + responseTitle
println "Error Resposne body: -> "+inputLine
throw new Exception("Error Code =$responseCode URL: $url")
}
具体在以下行中失败
cache[toBeCached] = inputLine
}, new Executors().newSingleThreadExecutor()))
inProcess[toBeCached].get(120, TimeUnit.SECONDS)
inProcess.remove(toBeCached)
if(RequestMethod == "POST")
{println "restapi.Request() ->"+inputLine
}
return inputLine
}
else
{
return cache.get(toBeCached)
}
}
public void waitForRequestifExists(String key)
{
if(inProcess.containsKey(key))
{
this.inProcess[key].get(120, TimeUnit.SECONDS)
}
}
public void clearCache()
{
this.cache = new HashMap <String, String>()
this.inProcess = new HashMap <String, CompletableFuture <?>>()
}
}
我遇到了类似的问题,结果是用于编译 groovy 代码的 maven 插件有一些问题。我使用 this answer.
解决了它基本上您需要明确指定 groovy-eclipse-compiler
和 groovy-eclipse-batch
的版本。在我的 POM 中,我将 metaversion 值设置为 LATEST
。相反,请尝试使用 <version>3.6.0-03</version>
等具体值。 (之后尝试清除您的 .m2 存储库缓存。)
如果您在构建过程中使用这些插件,则适用。
我在我们的 maven 项目中看到了 AbstractMethodError。似乎问题在于 groovy-all 和 groovy-eclipse-batch 的版本应该匹配。 eric-milles 在 groovy-eclipse issue 中的评论很有帮助。