CF Web Service invocation and Complex Types (Java Objects)

I am trying to call a java service from ColdFusion MX 8.0.1 using the following code.

     ws = CreateObject("WebService", "");
     vali = CreateObject("Java","vo.myapplication.ContactVO");
     wsResponse = ws.updateContact(vali);

I am the developer of the Java service, not a coldfusion programmer.

If you check the listed code... the problems occurs at line 3, creating the ContactVO object.

The call fails with "Object Instantiation Exception - Class not found: vo.myapplication.ContactVO", so i know CF is unable to load my class.
My question is why? The package is correct, and the class exists. I even tried "myapplication.vo.ContactVO" (as it seemed to expand the stubs in reverse)

My stubs have been generated into :


and i can see ContactVO in there, in the correct package.

I can make it work if i add the absolute path of the stubs directory to

Server Settings > Java and JVM > ColdFusion Class Path

Can anyone tell me why Coldfusion 8.0.1 is not dynamically loading the VO class for me at runtime, so that i can perform a CreateObject and pass the value.

Or suggest another way i can do it?

By the way, I REALLY want to use the Java object rather than a structNew(), because calling setters on my VO's automatically sets the modified marker on them.

Thanks in advance!
Who is Participating?
_agx_Connect With a Mentor Commented:
Yes, I double checked the docs on #2 and createObject is limited to classes in the CF class path, plus the ..\WEB-INF\lib and ..\WEB-INF\classes directories.

Unfortunately, I do not know a lot about the secret rituals CF performs under the hood.  For the most part the structNew() method has worked for me, so I have not had to resort to the cfhttp/soap route to get around CF's dark magic. But the closest explanation I have come across is this entry:

CFMX first retrieves the target service's WSDL, then runs this WSDL through the WSDL2Java tool (see below for more information), which outputs Java code defining Java-based classes equivalent to the XML data structures defined in the WSDL. This Java code is then compiled. The input arguments provided to are then mapped to the Java types generated by the compilation, and finally the Java stub functions for those types are called. In this fashion, CFMX *automatically* converts input values referenced in  or  tags to XML documents of the appropriate formats based on input argument format information provided in the service's WSDL.  
On the one hand, it does suggest that methods of the java classes are called.  But that wouldn't really explain why the 'secodaryIdIsDirty' flag still false in the final output, if the classes/methods are actually being called.  

I would be curious to see a small snippet of the ContactVO class. Just to see if it sheds any additional light on the subject. It may not, but it couldn't hurt ..
> Can anyone tell me why Coldfusion 8.0.1 is not dynamically loading the VO class for me at runtime

When you create a java object, ColdFusion only looks at jars and classes that are within in the CF class path.  I am pretty sure the stub path is not in the class path, which is why you get the class not found exception.

Off the top of my head, you might try packaging the stubs into a jar. Then put that jar in the CF class path.  It may work, it may not.  But you might be able to trick CF into thinking the  two  vo.myapplication.ContactVO classes are the same.
> I can make it work if i add the absolute path of the stubs directory to

Duh! I completely missed that line.  So if it works, what is the issue?  If you really want to use the java classes, they have to be in the class path when CF starts.  For the most part, it does not load classes dynamically at runtime (Though this does strike me as a little "off". Maybe because I have never done that with a stubs directory).

Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

kwikksilvaAuthor Commented:
> So if it works, what is the issue?

Well in reality this is not really a bad solution. but in the case of this particuar CF site, i do not want to transfer a JAR file every time the interface changes, i want CF to regenerate the stubs automatically.
If i use a jar, then the responsibility is on me, to transfer a new jar to them when the web service changes, even slightly. I would really like CF to load the class, based on the WSDL (i mean in fairness it certainly has dynamically loaded other classes related to the WS otherwise i would not be able to call it at all)
So then i could "CreateObject" the classes for the Webservice.

Yes, I hear what you are saying.  But you may have to do that anyway.  

1) I don't believe the stubs update automatically anyway.  IIRC, the definitions are cached because creating stubs for complex services can be very time consuming.  So that fact might put an end the question right there.

2)  The CF server certainly has access to the classes - it created them after all.  The problem is the createObject function doesn't.  IIRC, it only has access to classes in the _cf_ class path that is defined in the CF Administrator (or jvm.config) file.  The stubs directories aren't in that path.  So if you want to use those classes from createObject, you have to add them to the CF class path. I don't believe there is a way around that.

3.  You could try and tap into the underlying classloader or use an external one.  But that seems a bit convoluted and adds even more complexity to the equation.  Not to mention possible issues with paths.  IIRC, the stubs directories are dynamically named, which would present some challenges.  If it was even possible at all.
kwikksilvaAuthor Commented:
Thanks agx, i think point 2 is the killer, if thats right, then i'll just go the other way.

The other way being.....

     ws = CreateObject("WebService", "");
     vali = structNew()
     vali['id] = "1234";
     vali['secondaryId'] = '4855';
     wsResponse = ws.updateContact(vali);

The ONLY problem i have with this way, is that my java code looks like this.

public void setSecondaryId(String id)
       this.secondaryId = id;
       secodaryIdIsDirty = true;

So i get automatic dirty markers.For "update" methods, once CF does the setXXXXX, i know that those are the exact fields that need to be updated in the underlying data model.

When i use structNew(), it seems CF IS doing some magic underneath to turn it into a ContactVO.. BUT, the setter is like not being called or whatever?! because when it gets to my backend, the dirty markers are still all "false".

If you have any comments or advice on that, would appreciate it, otherwise i think we'll call this question answered anyway.

Thanks for you help agx!

Argh. I see the tags in the previous quote didn't mix well at all with EE's rich text styles :/

kwikksilvaAuthor Commented:
Thanks for your research _agx_, i will check the declaration of the VO, I don't have the code handy, (its in work), to check to se if there is any wierdness in the way its been put together.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.