Skip to main content
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with: Darren Walker
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with: Darren Walker

Loading Local Java Class Files Using URLClassLoader

By
Published in Comments (3)

Ok, this is nothing new. In fact, this isn't even for YOU. This is for me. This is coming right off of Spike-Fu's blog entry titled "Loading java class files from a relative path." He wrote it back in 2004; I am simply rewriting it here in my own words so that I can explain it to myself and see that it actually works and see if actually understand what the heck is going on. It's a post that I have know about for a long time but have just never taken the time to get into it. Now is that time.

If you follow my blog closely, you will know that I don't like things like class paths, path mapping, or basically, anything that requires the need to have special permissions on the hosting machine (ie. access to the admin or secured file system). Obviously, data sources are required, but that is once per project. I hate the idea of having to go back to the ColdFusion admin for much of anything. I like my projects to be very module. I like the idea of picking it up, dumping it somewhere else and just having it WORK. I know this creates duplicate code (for all you framekwork people) but I am sooo OK with that it's not even funny.

The ability to be able to load Java class files without them being in the ColdFusion list of Java class paths is something that fits into this ColdFusion application development mentality.

Ok, so let's look at the example. I downloaded Spike's HelloWorld.class file and have placed it in the same directory of the calling code. Then, I loaded it and called a method on it to see that it was working.

<!---
	Initialize the URL object to point to the current
	directory. In this case we are pointing using the file
	system, NOT the web browser, hence the "file:" prefix. This
	URL can point to any part of the file system irrelevant of
	the web-accessible parts of the system. This will happen on
	the server size, not the client side (of course) and
	therefore is not dependent on web-accessibility.
--->
<cfset objUrl = CreateObject( "java", "java.net.URL" ).Init(
	JavaCast(
		"string",
		"file:" & ExpandPath( "./" )
		)
	) />


<!---
	Get an array of URL objects. Since we cannot do this
	directly, (delcare an array of java object types), we will
	have to do this using the reflect array class. We can pass
	this class a Java class definition and ask it to create an
	array of that type for us.
--->
<cfset objArrayCreator = CreateObject(
	"java",
	"java.lang.reflect.Array"
	) />

<!---
	Ask the reflect array service to create an array of URL
	objects. Get the class definition from the URL object we
	created previously. When we create the array, we need to
	create it with the length of 1 so that we can add the URL
	to it next.
--->
<cfset arrURL = objArrayCreator.NewInstance(
	objUrl.GetClass(),
	JavaCast( "int", 1 )
	) />


<!---
	Now, we need to set the URLs into the array. This array
	will be used for the initialization of the URL class loader
	and will need to contain all the URLs that we need. Since
	we cannot work with these types of array directly in
	ColdFusion, we need to ask our array creator object to do
	the setting for us.

	My hope was that we did NOT have to use this SET method. I
	had hoped that I could call the AddURL() method on the
	URLClassLoader itself. Unforutnately, that method is
	Protected and I do not have permissions to access it.
	Hence, all of the URLs that we want to load have to be
	passed in during the initialization process.
--->
<cfset objArrayCreator.Set(
	arrURL,
	JavaCast( "int", 0 ),
	objUrl
	) />


<!---
	Now, we want to create a URL class loader to load in the
	Java classes that we have locally. In order to initialize
	this class, we need to pass it the URL array that we just
	created. Keep in mind that it contains all the URLs that
	we want to load.
--->
<cfset objClassLoader = CreateObject(
	"java",
	"java.net.URLClassLoader"
	).Init(
		arrURL
		)
	/>


<!---
	Now, get the URL class loader to load the HelloWorld.class
	class. Once it loads the class, we have to get a new
	instance of the Java class, HelloWorld.
--->
<cfset objHelloWorld = objClassLoader.LoadClass(
	"HelloWorld"
	).NewInstance() />


<!---
	Get the hello world object to perform an action. This should
	output the phrase "Hello World". This will show us that
	everything is working nicely.
--->
<cfoutput>
	#objHelloWorld.SayHello()#<br />
</cfoutput>

This outputs the phrase "Hello World!" It works quite nicely and very fast, at least on this tiny example. Still, very very cool that you can load Java classes without having to mess with the Admin, which you know I think is highly sexy.

Just a few notes. You will see when we load the class, we then call the Java method NewInstance() on the class. I don't fully understand how all this works, but I guess the first part just loads the definition for the class then the new instance call loads a new instance of that class. If you look at the Java 2 documentation, you will see that NewInstance():

"Creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized."

This is very interesting. If you use new instance, you cannot pass in an initialization list. That's good to know for future use (and experimentation).

Want to use code from this post? Check out the license.

Reader Comments

15,848 Comments

Rob,

I appreciate the link. It looks like the JavaLoader is doing the same thing that Spike was, just in a more packaged object. But, my intent was not so much to be able to do it, but more to understand how it worked and just to explore that it was indeed possible.

Thanks.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel