Problems adding jSoup to ColdBox 4.3 with Lucee 4.5.5.

Hello, in the past I would just drop the jSoup jar into ACF and get started with “myJsoup = createObject(“java”, “org.jsoup.Jsoup”);.” No problem. But now I’d like to do things the “ColdBox way” and am having problems!

First let me say that I am new to ColdBox and this way of doing things. I apologize in advance for what are likely to be very basic questions.

Next, do I need javaloader? The docs for ColdBox 4 say all I need to do is drop jars into /lib and I am good to go. Is this right? Because I tried that, reinited, and got started as above and got an error from Lucee,

cannot load class through its string name, because no definition for the class with the specified name [org.jsoup.Jsoup] could be found

Which to me suggests that Lucee or my app doesn’t know about jSoup, but I am not sure. I read that adding the path to the jSoup jar to createObject resolved the issue for some people – I tried that and got the same error.

What else do I need to do to get jSoup set up for my project? I would really appreciate any tips or pointers. Thanks a lot!

You’ll need to restart tomcat after adding the jars - reiniting won’t be enough. If you can get the jar loaded using createObject, then you can move onto doing it the “coldbox” way, but if it’s not working via createObject it’s because the jars aren’t in the classpath.

Tom.

Thanks Tom! I appreciate the help!

Tom is right. You need to restart Tomcat.

If you like to load the library it in ColdBox way, you need to install ForgeBox: JavaLoader
And then create /lib folder in your application site. Drop the jsoup.jar in /lib folder.

// Load the JavaLoader module
property name=“javaloader” inject=“loader@cbjavaloader”;

// Instantiate Jsoup
jsoup = javaLoader.create(“org.jsoup.Jsoup”);

Or, you can use wirebox which is my preferred method:

in WireBox.cfc:

map(“jSoup”).toDSL(“java:org.jsoup.Jsoup”);

in yourServiceModel.cfc:

property name=“jSoup” inject=“provider:jSoup”;

Thanks Ancient Programmer, I installed javaloader and copied the jsoup jar to /lib. Restarted and added the init code to my handler and got a new error,

The requested class could not be found. The requested class ‘org.jsoup.Jsoup’ could not be found in the loaded jars/directories

Which a new error is progress, I guess! :slight_smile: But I am not sure what else I need to restart to “wake up” my app to the presence of jsoup. It just seems like nothing knows it is there.

Any clues? Thanks!

From what I understand, you have two methods to load a java class. Either by dropping it into the /lib directory of tomcat, or by using the javaloader.

javaloader enables you to access java classes that are NOT loaded into the lib directory on the servelt container. That’s the only benefit of it, from what I understand.

So in short, if you have access to your lib folder, and you’re not writing an extension or something for other people to use - use native java loading using createObject or Wirebox DI.

If you’re on a shared environment, you don’t have access to /lib on the server, or you want to make your code re-useable by others - then use the javaloader instead.

Hope that helps.

Tom.

Thanks Tom! At this point I am open to pretty much anything lol… but here is what I am trying to do:

On my development machine, my app uses the Lucee server that came with CommandBox. On production, it is ACF 2016. I’d like to have everything packaged with my app so that I could just push the whole thing up to production w/o having to worry about copying jars to various locations.

So it sounds like javaloader may be the way to go for this situation. Now if I can only figure out what I am doing, I’d be in pretty good shape! :slight_smile:

Ok - if you’re using javaloader, and have used the commandbox module to get it working, the jar files need to go in the lib folder in the javaloader module. Is that where you’ve put them (i.e modules/cbox-javaloader/lib)?

Yes, except on my app it is modules/cbjavaloader/lib. Then in my event handler I injected it with

property name=‘javaloader’ inject=‘loader@cbjavaloader’;

But when I add jsoup = javaloader.create(“org.jsoup.Jsoup”); to any function, it triggers the “class not found” error.

Hmm - that looks correct. Unfortunately I don’t have any experience using the javaloader.

Try WriteDump(javaloader.getLoadedURLs()) to make sure it’s showing you the correct path for your lib folder.

Also, because you’re using the coldbox module, you can try this as a more direct loading method.

property name=‘jSoup’ inject=‘javaloader:org.jsoup.Jsoup’’;

WriteDump gives me

/modules/cbjavaloader/models/javaloader/support/cfcdynamicproxy/lib/cfcdynamicproxy.jar

which frankly does not mean much to me! I tried some of the other methods I found here but only a few worked. “QueryJars” unfortunately was one of those that did not work.

I am about ready to restart my whole machine just to make sure I am getting everything!

Hi guys, let me try to clear a few things up. There’s a lot of advice in this thread, and I think some of it is off a little.

  • There is no “coldbox way” to load jars. ColdBox doesn’t really care about your jars. The classloaders in the servlet container or the CF engine will need to load your jars. Strictly speaking, the framework (and the framework authors) don’t really care how you do it.
  • WireBox cannot load jars. It can instantiate Java classes that are contained in jars that have been already class loaded, but that no different than createObject( ‘java’, ‘com.foo.bar’ ).
  • If you just want to have a jar available to your entire application, then use the this.javaSettings in your Application.cfc. That is a CF engine feature supported by all recent versions of Adobe CF and Lucee and I don’t even think it requires a restart. this.javaSettings can point to ANY folder, but we tend to include a /lib folder in our Coldbox application templates just as a suggestion, which is why you will see references to a lib folder in our docs. Coldbox and WireBox don’t do anything with that folder, but our app templates include the this.javaSettings boilerplate to load jars from there.
  • Java Loader is ONLY needed if you need your app to run on CF9 which is before this.javasettings or if you want to wrap up what you’re writing into a Coldbox module that can be distributed to any app and can’t rely on a particular set of this.javaSettings to exist. I consider this to be an annoying deficiency of CF engines, BTW. If you’re not writing a distributable module and you’re not running a really old version of CF, you don’t need Java Loader!
  • You ONLY need to put jar files in your Tomcat (or servlet) container’s lib folder as a last resort if you need them picked up by the core CF engine. The only use case I know of for this honestly are JDBC drivers. The CommandBox way to do this is to use the “app.libDirs” setting in your server.json. Don’t ever manually copy files around.

Brad is correct. Brad is always correct.

Hah, my wife might disagree :slight_smile:

Thanks!

~Brad

ColdBox/CommandBox Developer Advocate
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thanks Brad this is great, I appreciate the clarity. I pulled out all the javaloader stuff and moved the jsoup jar to /lib per your #3 below. Do I need to do anything else? Declare some properties in my event handler or something? Because simply adding

myJsoup = createObject(“java”, “org.jsoup.Jsoup”);

or

myJsoup = createObject(“java”, “org.jsoup.Jsoup”).init();

to either the handler or model takes me back to

cannot load class through its string name, because no definition for the class with the specified name [org.jsoup.Jsoup] could be found

I am sorry for being such a pest! But I don’t understand what I am missing. I am trying hard to get away from our old procedural code and into mvc (that’s mostly what I meant by “the ColdBox way,” sorry if that offended anyone). For the most part it has been going well, and I appreciate the benefits. But once in a while I bump up against stuff like this that is frustrating to me – I know it should not be this difficult, and I am clearly doing something wrong, but I cannot figure out what it is. Makes me feel even dumber than normal! :slight_smile:

What this.javaSettings do you have in your Application.cfc? if you didn’t create your app from one of our application templates, then you probably don’t have that.

https://github.com/coldbox-templates/advanced-script/blob/master/Application.cfc#L14-L18

Without those lines above, putting jars in a lib folder won’t do anything at all!

Thanks!

~Brad

ColdBox/CommandBox Developer Advocate
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thanks Brad I am using an application template. I still have “drop-jars-here.txt” in my /lib in fact haha! My application.cfc uses

// Java Integration

this.javaSettings = {

loadPaths = [ “.\lib” ],

loadColdFusionClassPath = true,

reloadOnChange= false

};

So I finally found a solution! I am not sure why it works, but this is what fixed it for me:

this.javaSettings.loadPaths = directoryList(expandPath("/lib"));

See the discussion at Stackoverflow for more info. Thanks to Tony Junkes for the answer, it works great for me. And I appreciate everybody’s help here, too!