Solved

CF Web Service invocation and Complex Types (Java Objects)

Posted on 2009-04-09
8
399 Views
Last Modified: 2013-12-24
I am trying to call a java service from ColdFusion MX 8.0.1 using the following code.

<cfscript>
     ws = CreateObject("WebService", "http://myserver.us/webservices/WebInterface?WSDL");
     vali = CreateObject("Java","vo.myapplication.ContactVO");
     vali.setId(1234);
     vali.setSecondaryID(45855);
     wsResponse = ws.updateContact(vali);
</cfscript>

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 :

C:\jrun4\servers\cfusion\cfusion-ear\cfusion-war\WEB-INF\cfusion\stubs\WS-254617805

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!
0
Comment
Question by:kwikksilva
  • 5
  • 3
8 Comments
 
LVL 52

Expert Comment

by:_agx_
ID: 24111526
> 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.
0
 
LVL 52

Expert Comment

by:_agx_
ID: 24111835
> 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).

0
 

Author Comment

by:kwikksilva
ID: 24113410
> 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.

0
 
LVL 52

Expert Comment

by:_agx_
ID: 24113949
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.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:kwikksilva
ID: 24115742
Thanks agx, i think point 2 is the killer, if thats right, then i'll just go the other way.

The other way being.....

<cfscript>
     ws = CreateObject("WebService", "http://myserver.us/webservices/WebInterface?WSDL");
     vali = structNew()
     vali['id] = "1234";
     vali['secondaryId'] = '4855';
     wsResponse = ws.updateContact(vali);
</cfscript>

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!

0
 
LVL 52

Accepted Solution

by:
_agx_ earned 50 total points
ID: 24117700
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.
http://livedocs.adobe.com/coldfusion/8/htmldocs/functions_c-d_17.html#3824742

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 ..
0
 
LVL 52

Expert Comment

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

0
 

Author Closing Comment

by:kwikksilva
ID: 31568744
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.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Introduction In this tutorial, I'll explain how to create an animated progress meter in a wireframe prototype developed using Axure RP 7.0 - a leading prototyping tool for designing web sites and software. (For more information about Axure and gett…
Objective of This Article In 1990’s, when I was a budding software professional, I had a lot of confusion about which stream or technology, I had to choose to build my career. In those days, I had lot of confusion like whether to choose System so…
The purpose of this video is to demonstrate how to reset a WordPress password if you are locked out and cannot reset the password. A typical use would be if you cannot access the email to which WordPress would send the password recovery email to…
The purpose of this video is to demonstrate how to set up the permalinks on a WordPress Website. This will be demonstrated using a Windows 8 PC. Go to your WordPress login page. This will look like the following: mywebsite.com/wp-login.php : Go t…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now