Calling MolConverter.Builder from a signed Java Applet

User 7bdb8e43f2

10-10-2011 19:48:00

Hi,


I am attempting to instanciate and call MolConverter.Builder from my Java Applet when Marvin Beans is installed on the client computer. My goal is to integrate with the allready installed Marvin Beans on the computers from my Applet.


		try
{
System.out.println("Initilaizing Marvin by path");


//Build a string array of all .jars in the Marvin Beans distribution
File f = new File("C:\\Program Files\\ChemAxon\\MarvinBeans\\lib\\");
File[] fs = f.listFiles();
URL[] us = new URL[fs.length];
for(int i = 0;i < fs.length;i++)
{
File fLoop = fs;
us = new URL("jar:file:/" + fLoop.getAbsolutePath() + "!/");
}

URLClassLoader ucl = new URLClassLoader(us);

Class.forName("chemaxon.formats.MolConverter", true, ucl);
Class.forName("chemaxon.formats.MolExporter", true, ucl);
Class c = Class.forName("chemaxon.formats.MolConverter$Builder", true, ucl);

System.out.println("Initilaized Marvin");

System.out.println("Class is: " + c.getName());

System.out.println("Initilaizing MolConverter");

MolConverter.Builder mb = (MolConverter.Builder)(c.newInstance()); // This line fails with a ClassNotFound Exception

System.out.println("Initilaized MolConverter");

}
catch(Exception ex)
{
System.out.println("Exception initializing Marvin. Ex: " + ex.toString());
}


My problem is that when I try to instanciate the MolConverter.Builder from the Class I got from the URLClassLoader it fails with a ClassNotFound exception.


Do you have any hints on how to do this? Or should I just revert to sending the whole Marvin Applet over the line to the client instead? 


The reason for this is to just have to send a small (signed) footprint applet that then consumes the installed Marvin jars. Perhaps this workflow is prevented by some security mechanism?

ChemAxon 7c2d26e5cf

11-10-2011 12:32:32

Hi,


Although I do not have big experience in URLClassloader but I have a tip.


In the Marvin Beans package, the MarvinBeans.jar is the essential main jar. Although it includes only the core classes of Marvin Beans API but it includes a "Class Path" entry in its META-INF/MANIFEST.MF that describes where other jars are located that are part of the API.


Although the chemaxon.formats package is in the core MarvinBeans.jar but it can refers to certain classes that are located in another jars.


By desktop application, only MarvinBeans.jar has to be in the
classpath. In this case, the default classloader lookups every required classes with
the help of inner classpath of the main jar.


I can imagine that URLClassloader cannot do it automatically.


Have you tried to launch MolConverter as a command line application from java?


java -classpath <MarvinBeans.jar absolute path> chemaxon.formats.MolConverter

I guess it is more easy than hacking the class loader.

User 7bdb8e43f2

11-10-2011 12:55:50

Hi Tamas, 


Thank's for your reply.


I suspected that what you say was the case, that the MarvinBeans.jar is the main but it uses other jars in turn.


That is why instead of just loading MarvinBeans.jar in the URLClassLoader I try to loop over all .jars in the /bin/ folder and load them all. I guess the problem might be in the internal classes (like the MolConverter.Builder) where the classloader syntax seems to be MolConverter$Builder when I inspect it. What is the most simple class in the API that I should test to instanciate in your oppinion?


Currently I am doing this just as you describe by starting a new process. The effort of moving to direct API calls are part of refactoring. It is quite messy to asynchronously wait for the processes, file-locks of output files and such on Windows, MacOS and Linux. If I am able to just consume the API from the applet I could get rid of alot of code that just handles OS specific cases of the operations.


I can ofcourse try to have my Applet's manifest have class paths to the most common target installation folders of Marvin on the different platforms. Maybe that will help the classloader to find the internal classes.


Regards,
Erik



ChemAxon 7c2d26e5cf

12-10-2011 09:45:15

There are several "simple" class in the core jar that do not have internal classe(s) and do not refer other chemaxon.* classes. E.g.:



Try one of them by URLClassLoader.


To tell the truth, I do not understand your concept. Why do you consume the Marvin Beans API from applet on client side?


Have you already considered to place molecule conversion or any other operations that requires the Marvin Beans API to server side?


On server side, you can create with JSP pages or servlets in which you can integrate the Marvin Beans API. They can communicate with the client side via http protocol.
You can also access servlets directly from an applet with the help of the java.net API. But you can post your request from javascript too.

User 7bdb8e43f2

12-10-2011 11:14:34

Hi Tamas,


Let me try to explain why.


Our client is a JavaScript RIA client executing in the browser of the user. The JavaScript client uses a Java Applet to break out of the browser sandbox and integrate with the user's desktop. For instance with the clipboard, file-system, Microsoft/Open/Libre office.


When a user wants to edit chemistry we integrate with whatever drawing package the user has installed. If the user has ISIS/Draw we connect to that. If the user has ChemDraw we connect to ChemDraw. And if the user has Marvin we connect to Marvin.


I don't want to redistribute or be dependant on any 3rd party vendor of chemistr drawing tools, I want to integrate with whatever the user has installed (prefers) and gracefully degrade the functionality into read-only for chemistry if no tool is installed. And refer the user to Chemaxon for instance, to purchase and install Marvin if Marvin is the preferred tool.


This all works. If we use the user's computer to render, calculate etc. the system will scale with the number us users much better then if we perform all this server-side. We are trying to keep the server as thin as posssible. However, the solution with starting processes on the client for Marvin is sub-optimal since it should(?) be possible to consume the API directly from the Java applet instead of by executing scripts in the operating system and waiting/guessing when they are complete.


I will look into this further and if I find a solution I'll post it in the thread for future reference. If you have any ideas/suggestions please let me know.

ChemAxon 7c2d26e5cf

17-10-2011 16:27:00

Thanks for the explanation. The situation is already clear.


In case, any Marvin applet is running beside your code, it would explain the class loader issue. If a Marvin applet is running in the same JVM than the beans loader applet, it can causes problem. Marvin Applets and Beans packages have been built by different way. The applet does not contain certain classes that are part of the beans package.
If some classes are loaded from the Marvin Applets package and other ones from the Beans package, it can cause conflict.


If you have problem with the loading of MolConverter$Builder, I recommend to use MolImporter and MolExporter classes to import/export and convert among various chemical formats.


Anyway, MolConverter$Builder has been introduced in Marvin 5.2.3. But there is not a real chance that an ancient Marvin Beans version is located on the client side. Despite of it, I would check the version of the Marvin Beans package on the client's machine.