Thursday, February 24, 2011

Netsuite and Coldfusion: compiling stub classes just got easier (or has been easier for quite some time, but I just found out about it)

UPDATE: I may have spoken too soon on this post... more to come.

--

As of ColdFusion 8 (and I also confirmed this in CF9), it appears that at least one portion of the once ridiculously convoluted process of getting ColdFusion to play nicely with SuiteTalk, Netsuite's web service API, is now a lot easier. In CF8, a parameter was introduced to the CreateObject() method that allows passing command line parameters for wsdl2java.

The problem with CFMX7 was that it wouldn't auto-compile all of the stub classes for SuiteTalk / Netsuite, either due to quietly timing out due to the sheer size and depth of the wsdl, or more likely because it was ignoring unreferenced elements. To cover both of these scenarios, we can simply up the timeout on wsdl2java and force it to compile classes for unreferenced elements.

<cfset ws = createobject( "webservice",
"https://webservices.netsuite.com/wsdl/v2010_1_0/netsuite.wsdl",
"NetSuitePort",
"-a -O 2000") />

"webservice" = type of object to create
"https://webservices.netsuite..." = URL of Netsuite WSDL. Replace this with the latest version or whatever version you prefer to use.
"NetSuitePort" = name of the web service port
"-a -O 2000" = -a (compile all elements, even unreferenced) -O 2000 (set timeout to 2000 seconds)

Thursday, March 25, 2010

Preserving structure sort order in ColdFusion

ColdFusion doesn't preserve the order in which elements were assigned to the structure. If you want to quickly and consistently loop through the items in a structure in the order in which they were assigned, the answer is simply to not use a ColdFusion structure. It's easier (and less stupid) than it sounds.

Instead of this:
<cfset mystruct = StructNew() />

Do this:

<cfset mystruct = createObject("java", "java.util.LinkedHashMap").init() />

A java LinkedHashMap object can be treated exactly the same as a structure created by StructNew(). You can assign values the same way, and you can even loop over it the same way using <cfloop collection="...">. Need to do a StructSort? You can do that, too. The only difference is that cfloop will loop over it in the order in which the elements were assigned.

Saturday, February 06, 2010

See my goofy mug on TV!

If you are curious about my non-technical side, catch me on television tomorrow on DIY Network in an episode of Bathtastic airing at 10 am central/11 am eastern tomorrow, Sunday February 7th as part of DIY's Super Bowl-themed marathon, dubbed the Toilet Bowl. How appropriate. In the episode, we gut my bathroom and turn it into a lavishly swank hot box. Whatever that means. Oh, and it looks like they are going to play up my "lack of skill" when it comes to home remodeling, but considering I remodeled the rest of my house with my own two hands, don't believe everything you see on television. *grin*

Oh, and if you don't have cable or don't get DIY Network, I believe they make the episodes available on the DIY Network website not long after they air.

Wednesday, December 23, 2009

Logging into Netsuite with ColdFusion or Java - Code Sample

Every now and then, I get a request about sample code for logging into Netsuite. I often forget that I started working with Netsuite in CF before I commonly used native java objects. It took me some tinkering to figure out, but when dealing with Netsuite specific datatypes and objects in ColdFusion, sometimes CF will often correctly translate an array, integer, string, etc to an equivalent compatible with the SOAP request, however often I just skip the middle man and eliminate risk by casting the variable or creating a native instance of the java stub class.

Here is the full java equivalent (I haven't tried to compile this, so you may need to make some tweaks)

//java pseudo-ish code (meaning I haven't actually tried to compile this)
import java.net.URL;
import com.netsuite.webservices.platform_2009_1.NetSuitePortType;
import com.netsuite.webservices.platform_2009_1.NetSuiteServiceLocator;
import com.netsuite.webservices.platform.core_2009_1.Passport;

String YourNetsuiteAccountNumber = "123456789";

URL endpoint = new URL("https://webservices.netsuite.com/services/NetSuitePort_2009_1?c=" + YourNetsuiteAccountNumber);
NetSuitePortType nsws = NetSuiteServiceLocator.getNetSuitePort(endpoint);
nsws.setMaintainSession(true); // maintain this session
nsws.setTimeout(1000 * 60 * 60 * 2); // set 2 hour timeout period
Passport passport = new Passport();
passport.setEmail("youremail@blahblah.com"); // email address used to log into netsuite (must be set up as web service user)
passport.setPassword("password1234");
passport.setAccount(YourNetsuiteAccountNumber);
nsws.login(passport);

Monday, March 16, 2009

Netsuite web service and ColdFusion 8

I recently posted updates to previous posts regarding problems with web service connections between ColdFusion MX 7 and Netsuite, but thought this matter warranted a post of its own. Perhaps you have experienced issues creating a web service connection with Netsuite, whether it's through the ColdFusion Administrator or through the CFINVOKE tag or CreateObject function. The fact of the matter is that Netsuite's extraordinarily complex and deeply nested WSDL, which references XSD within XSD and beyond, appears to give ColdFusion a headache, and it silently gives up on compiling the stub objects before the job completes (there are over 600 java stub class files generated for Netsuite's 2008_1 WSDL). I have now confirmed that this an issue in CF8 in addition to CFMX7. I get around this by compiling the stub classes from the command line and dumping them into a nice, portable jar file.

I will readily admit that it is possible I am missing something in this problem. There could very well be a timeout issue with ColdFusion compiling the stub classes, but it doesn't throw an error. And while you can easily adjust the timeout for WSDL2Java from the command line, I am not aware of a way to increase the timeout in the ColdFusion Administrator. If anyone else is aware of a way to do this, I'd love to hear from you in the comments or an email. If I get an answer, I'll be certain to post it here.

Sunday, February 15, 2009

Apache Axis (java.io.IOException: Non nillable element '[ElementName]' is null)

Much has been written on this frustrating error (seemingly most of it along the lines of "Hey, guys, I have this problem. Anyone know what's up? ... Hello? Guys? Anyone?" Often, the are older posts referencing a known and now-fixed issue in Apache Axis 1.2 involving elements whose "nillable" attribute is set to true. However, when no value is set for that element, the aforementioned java.io.IOException is thrown. In my case, I was using ColdFusion MX7, a jar file comprised of java stub classes ripped with WSDL2Java, and a version of Axis 1.2 customized to address an issue in accessing NetSuite's web service. The element in question was a datetime field, of type java.util.Calendar specifically. Due to the web service provider's documented business logic, setting a value in that field would actually result in the request being rejected outright, so setting a dummy value was not an option. Additionally, I tried setting the element to an unitialized Calendar object, but that resulted in the same error as not setting it at alll.

Solution

My first course of action was to upgrade to Axis 1.4. No dice. I still was getting the same error. My next step was to delete the jar file I'd made of the WSDL classes from the CFusionMX7/lib directory (if you've read previous posts here regarding ColdFusion and its interactions with Axis, you understand why I tend to lean toward that method instead of using the auto-compiled stub classes in the ColdFusion installation directory), added the stub class file directory I was using to the Java classpath in ColdFusion administrator, and restarted the CF service. Blam! Problem fixed.

Post Mortem

To be honest, I am not 100% certain what the issue was, but I strongly suspect this was an issue between the version of Java that had compiled the Axis jar file distribution, the version of Java our ColdFusion installation was running on, and/or the version of Java I had used to manually compile the stub class jar file I had been using previously. If anyone else has had this issue and has further details into the "why" of the fix, I'd love to hear them.

Thursday, May 29, 2008

Automatic page refreshes are so 1998

Dear CNN.com, MNspeak, and the internet at large, I don't know if you are aware, but automatically refreshing the web page I'm reading is extraordinarily annoying and completely unnecessary. There was once a time many years ago where automatically refreshing a news site or any number of other types of pages was useful. These days, however, I believe it actually drags down your reader's experience on your site. If I want to see the latest version of your page, I will click the Reload button in my web browser, thank you very much. I do not care to be in the middle of reading something then have the page suddenly reload itself. Now I have to hunt down what I was reading and pick up where I left off, assuming the item I was reading wasn't old enough to be archived off of the front page. And God forbid it's a longer item, and I have to go through this process multiple times before I finish.

To eliminate any confusion, the type of page refresh I'm talking about includes those in <meta ...> tags and javascript setTimeout() and setInterval() calls that unceremoniously reload the entire page you are viewing. Why in this day and age of RSS, AJAX, Flash, and hell, even iframes would you still use auto-refreshes? I will concede that there might continued value for mobile versions of websites where timely delivery of information is key (think live sports scores and stock prices), as there are still a great number of mobile devices that do not support Flash (iPhone anyone?). But taking away a reader's choice in the age of Web 2.0 and ubiquitous connectivity tells me that you just don't get it.