Calling external library class with a $ causes an "Invalid Class Name" error

79 views
Skip to first unread message

Marcus

unread,
Feb 19, 2018, 6:16:41 AM2/19/18
to Icy imaging
Hi,

I've written my own plugin to prepare some images from a stack and then upload them to AWS. 

To facilitate the upload I'm using the jets3t library. To make use of this library, I initially had the library's class files and all dependencies packaged in with my plugin. When launching the plugin from Eclipse with the "R" or "D" button this worked fine. However when uploading the plugin to the Icy site and installing it through the plugins interface, it throws an "Invalid class name" error. 

As per this post, I moved the classes into a separate PluginLibrary, and made this a dependency of my plugin. Again, launching from Eclipse with "R" or "D" means the plugin runs with no error; however launching with "U" or installing the plugin in Icy from the plugins bar causes the same "Invalid class name" error. 

The specific class causing the problem is "Invalid class name: org.jets3t.service.utils.RestUtils$ConnManagerFactory". There is no problem calling the rest of the library classes from the plugin, but as soon as this class is required this error appears. I've checked in the jar file which is installed by Icy into the plugins folder and the class is definitely there!! So I think perhaps it's something to do with the $ in the class name? Poking around the Icy4Eclipse source code shows me my plugin only works when I launch with "bypassJarclassloader", but this doesn't really help me, except that I think I'm having problems getting my RestUtils$ConnManagerFactory into the classloader? 

(I also have a very similar plugin written for ImageJ, which runs just fine in my installation of FIJI. However when I run that plugin through the ij bundled in Icy I have exactly the same Invalid class name error!)

Any help would be much appreciated; it's frustrating that this seemed to work in debug mode but I can't distribute it! 

Many thanks,
Marcus

Stephane

unread,
Feb 21, 2018, 2:01:55 PM2/21/18
to icy-so...@googlegroups.com
Hi,

I tried your plugin and indeed i obtain the same issue :

org.jets3t.service.ServiceException: Request Error: Invalid class name: org.jets3t.service.utils.RestUtils$ConnManagerFactory
    at org
.jets3t.service.impl.rest.httpclient.RestStorageService.performRequest(RestStorageService.java:625)
    at org
.jets3t.service.impl.rest.httpclient.RestStorageService.performRequest(RestStorageService.java:279)
...
    at java
.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: Invalid class name: org.jets3t.service.utils.RestUtils$ConnManagerFactory
    at org
.apache.http.impl.client.AbstractHttpClient.createClientConnectionManager(AbstractHttpClient.java:286)
    at org
.apache.http.impl.client.AbstractHttpClient.getConnectionManager(AbstractHttpClient.java:437)
    at org
.apache.http.impl.client.AbstractHttpClient.createHttpContext(AbstractHttpClient.java:246)
...



Looking on internet i found some pages about this error :
https://github.com/literalice/gradle-aws-s3-sync/issues/18
https://jira.pentaho.com/browse/PDI-16813
https://stackoverflow.com/questions/10144188/jets3t-connects-without-exception-but-invalid-class-name-when-i-try-to-do-a

I think the problem comes from the fact we use a specific class loader for the plugins and jets3t doesn't like it.
Is there some ways to change or specify a specific class loader to work with in jets3t ?
Or maybe to change the context class loader before using jets3t methods, something as :
 Thread.currentThread().setContextClassLoader(SystemUtil.getSystemClassLoader());
or
 Thread.currentThread().setContextClassLoader(PluginLoader.getLoader());

Don't forget to restore back the good context class loader after the jets3t method call..
Problem is that you need to test using an external Icy (with your JAR files) so you are sure that both plugin are loaded in the Plugin class loader (and not in the system class loader as when you're using eclipse).

Best,

- Stephane

Marcus

unread,
Feb 21, 2018, 7:26:53 PM2/21/18
to Icy imaging
Hi Stephane, 

That seems to have done the trick, thanks very much! 

It seems quite a specific problem, but just in case anyone has the same issue and finds themself here: SystemUtil.getSystemClassLoader() didn't fix the error, but the following code did:

ClassLoader goodCl = Thread.currentThread().getContextClassLoader();            
Thread.currentThread().setContextClassLoader(PluginLoader.getLoader());
    // ...
    // Code requiring PluginLoader class loader context
    // ...
Thread.currentThread().setContextClassLoader(goodCl);

I'll have to test it out on a computer in the lab tomorrow, but all looking good for now! 

Thanks,
Marcus

P.S. Congrats on your nice Nature Comms paper last week! :)

Stephane

unread,
Feb 22, 2018, 9:25:51 AM2/22/18
to Icy imaging
Hi Marcus,

I'm glad that helped to solve your problem, hopefully now your plugin will work without any troubles :)
Thanks for providing the piece of code which made the trick (and indeed in general we just have to force the PluginLoader class loader in place of current one).

The paper was a long run (not necessary for me but for my colleagues working on...), we are glad to finally see it published =)

Best,

- Stephane
Reply all
Reply to author
Forward
0 new messages