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.

Wednesday, April 16, 2008

Process for generating Netsuite java files, compiling stub classes, and creating jar file

UPDATE February 24, 2011: I recently learned as of ColdFusion 8 that you can set wsdl2java command line parameters when calling CreateObject to create a web service object. Complete details are in this post.

UPDATE March 8, 2009: Since this was first posted, I verified that the incomplete stub file compilation issue appears to be an issue in ColdFusion 8, as well. I haven't tested it, but I have no reason to believe that the jar file trick described below wouldn't work in 8.

If you've read other posts I've done about ColdFusion and Netsuite integration, you may recall that I solved an issue with MX7 refusing to compile all of the necessary stub files from the Netsuite WSDL by manually compiling them and creating a jar file. This used to be a huge hassle for me each time Netsuite released an upgrade. This time, however, it should be a ridiculously smooth process. I know the following steps will look intimidating if you are not familiar with Apache ANT or Apache Ivy, but trust me, they will make your life a lot easier.

Someone recently wrote me with some questions about this process, and I thought I would post this for everyone's benefit. Or at least I hope it's for your benefit and not your additional confusion. *grin*

Oh, and a couple of notes. I have not done any development in ColdFusion 8, so some of the steps and issues below may not apply. In fact, this entire process may not be necessary at all for all I know. Also I'm quite green when it comes to ANT and Ivy, so as with everything else I post here, if there is a more efficient way to any of these steps, I'd love to hear from you.

Assumptions for this process (modify as necessary for your environment):

  • [Netsuite WSDL version] = 2_6_0
  • [CF install path] = C:\CFusionMX7
  • You are using ColdFusion MX 7 (Notes for ColdFusion 8 will be given where necessary)
  • [java install path] = C:\j2sdk1.4.2_12
  • [major java version that your CF installation uses] = 1.4
  • [stub class target] = C:\netsuiteclasses\2_6_0
  • [Apache Axis version] = 1.2.1

Prerequisites:

  • You have Apache ANT 1.7.0 or higher installed and have all environment variables set per its installation documentation. (Download binaries and see documentation at http://ant.apache.org/)
  • You have Apache Ivy 2.0.0 beta 2 or higher installed and have all environment variables set per its installation documentation. (Download binaries and see documentation at http://ant.apache.org/ivy/)
  • A version of the java jdk compatible with the java runtime version of your ColdFusion installation.
  • NOTE: This item is only for ColdFusion MX7 and likely does not apply to ColdFusion 8. A modified version of the Apache Axis 1.2 jar file (axis.jar) (distributed by Netsuite to fix a login issue caused by how cookies are passed by Axis in the HTTP header) was copied into [CF install path]\lib, and the ColdFusion server was restarted afterward.

Generate and Compile Process:

1. Generate java class source code (windows dos window).

[java install path]\bin\java -cp [CF install path]\runtime\lib\wsdl2java.jar org.apache.axis.wsdl.WSDL2Java -v -O 120 -a -o [stub class target] https://webservices.netsuite.com/wsdl/[Netsuite WSDL version]/netsuite.wsdl

2. Create Apache ANT build file.

Create a file named build.xml in [stub class target] with the following contents (pay attention to bracketed areas that you will need to modify accordingly):

<?xml version="1.0" encoding="UTF-8"?>
<project name="netsuite_[Netsuite WSDL Version]" default="init" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<description>
Build file for Netsuite [Netsuite WSDL Version] WSDL.
</description>
<property name="classes.dir" location="classes" />
<property name="dist.dir" location="dist" />
<property name="dist.jarfile" value="netsuite_[Netsuite WSDL Version].jar" />

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="${lib.dir}/[type]/[artifact]-[revision].[ext]" conf="runtime"/>
</target>

<target name="clean" description="Clean up output directories.">
<delete dir="${classes.dir}" />
</target>

<target name="compile" depends="-init" description="Compile all sources.">
<mkdir dir="${classes.dir}" />
<javac srcdir="." destdir="${classes.dir}" debug="true" deprecation="true">
<compilerarg line="-source [major java version that your CF installation uses]" /> <!—NOTE: The “-source” option may not be necessary for CF8 -->
<compilerarg line="-classpath [CF install path]\lib\axis.jar; [CF install path]\lib\jaxrpc.jar" />
</javac>
</target>

<target name="rebuild" depends="clean,compile" description="Cleanly compiles all sources." />

<target name="-init">
<!-- Create the time stamp. -->
<tstamp>
<format property="TODAY_US" pattern="dd MMM yyyy HH.mm" locale="en_US" />
</tstamp>
</target>

<target name="dist" depends="rebuild" description="Creates the binary distribution.">
<mkdir dir="${dist.dir}/${TODAY_US}" />
<jar basedir="${classes.dir}" destfile="${dist.dir}/${TODAY_US}/${dist.jarfile}" />
</target>

</project>

3. Create Apache Ivy config file.

Create a file named ivy.xml in [stub class target] with the following contents (pay attention to bracketed areas that you will need to modify accordingly):

<ivy-module version="2.0">
<info organisation="apache" module="hello-ivy"/>
<dependencies>
<dependency org="apache" name="axis" rev="[Apache Axis version]"/>
</dependencies>
</ivy-module>

4. Compile files and generate jar file.

Open a Command Prompt window and change directories to your [stub class target] directory and run the following command:

ant dist

You may see multiple warning messages throughout the compile process, but as long as you see a BUILD SUCCESSFUL message upon completion, there shouldn’t be any problems. Copy the generated jar file (the output of the ant command should indicate the filename and location of the jar file) to [CF install path]\lib and restart your ColdFusion Application Server service.

Wednesday, March 12, 2008

Jeremy to Microsoft Live "quality" bot: you're doing it wrong

I don't recall exactly how long ago it was, perhaps a few weeks or months ago, but I started noticing a few odd referrals in the traffic stats for one of my other blogs. At the time, this was happening at least a couple times a day. I would see one-word searches coming from search.live.com. It took me a few days to realize that this was some sort of Microsoft search bot. Since it only hit my site a couple of times a day, I didn't think much of it. But this morning I checked my stats, and out of 128 unique visitors for the day up to that point, 18 of those visits were from the live.com bots. That comes to 14% of my traffic. I did a search and learned that these are "quality control" bots of some sort. Really, Microsoft? What is so special about your search engine that you have to skew everyone's traffic statistics? I have not once had a human referred to my site by the live.com search engine, so I have no qualms over hiding my site from their bots entirely, or generating completely bogus content specifically for them. Either way, I've set up my web stat software so that range of IP addresses is filtered. Surely Microsoft can find a better method of controlling their quality. Wait, look who I'm talking about. Never mind.

Wednesday, February 27, 2008

Save yourself the effort of defining the same code for multiple javascript events

If you ever have a situation where you basically want to run the same code for a bunch of different events on an html element like an input, it's a pain in the ass to maintain if you change the logic and need to change all of the event parameters. I discovered you can directly call another event so you don't have to define and maintain the same code in multiple places. I realize you can do something very similar by using addEventListener, but I just thought this was kind of cool.

e.g.
// define the onchange event and call the same code for onmouseover, onmouseout, and onclick

// Now if you make changes to onchange, you don't need to copy those changes to the other events.


<input ... onchange="myFunctionDoYouLikeIt(this, 'valueadded', false, 0); compareSomeValues('placeholder', false, true, 'the google webz');"

onmouseover = "eval(this.onchange + '\;anonymous()\;');"

onmouseout = "eval(this.onchange + '\;anonymous()\;');"

onclick = "eval(this.onchange + '\;anonymous()\;');" />

Friday, February 22, 2008

Combine multiple Twitter feeds on Blogger

NOTICE August 12, 2009: If you are having issues with the hosted version of my twitter widget (i.e. you are not linking to a local copy of the javascript file on your own server), it looks like my bandwidth has been exceeded on my googlepages account. Frankly, I can't imagine how that tiny .js file could exceed my bandwidth, but perhaps someone with a very popular site is linking to it. In any case, I'm working to find a permanent, alternate host. For the latest updates on this issue, check back here or follow my Twitter feed.

Oh, and I probably will have to find a paid host, so if you are a user of this widget and would like to help out, a donation would be appreciated (the Donate button is in the right hand column on this page).



UPDATE 1/25/2009: I have received a few feature and bug fix requests. That list is available here. I have a fairly packed schedule through the spring and mid-summer of 2009, so it may be quite some time before I am able to complete these. But you are welcome to download a copy of the code, add these or other features you'd like to see, and fire it back to me. This code is non-commercial, not-for-profit open source, so I will gladly give full credit to whomever contributes code if I decide to include it in the version that is distributed here. And while this is not-for-profit, if you should wish to thank me for the time I've invested in this project, I am happy to accept even the smallest PayPal donation (see the Donate button to the right on this page). ;-) And now back to the original post.

This Blogger widget I created is based on the original widget provided by Twitter. This one, however, will let you combine multiple users' feeds into one and sort them by time. This is as opposed to showing your entire timeline, including everyone you follow. Perhaps someone has already written something like this, but damned if I could find it. Constructive criticism is welcome, particularly since this is my first crack at creating a blogger widget.

Configure and add the widget here.

I promise to post more documentation for this feature later, as there are other nifty things you can do to control the style of the output, including creating a "mask" to define the format of your output, and inclusion of data like the user profile, user homepage link, user profile image, etc.

Caveats: The number you are defining in the form does NOT mean that only the last n posts from your pool of users will appear. It means that the last n posts from each user will be shown. For example, you've set the twitter number to 3. User1 posted a single twitter 4 days ago, but User2 posted 4 twitters today alone. You will see the last 3 posts from User1 and the last 3 posts from User2.

Tuesday, February 12, 2008

A warning regarding calculating sales commissions in NetSuite

Are you seeing discrepancies in your sales commission figures? It recently came to our attention that when calculating sales commissions, NetSuite's sales commission module ignores the first line item on a transaction (invoice, sales order, etc) if it is a markup item, discount item, etc. They claim this is by design but cannot produce any existing documentation that would have clued us in on this "useful feature." Unfortunately for us, a large portion of invoices had markup items or discount items on the first line. Since NetSuite continues to insist this is not a bug, I ended up having to write a script to re-sort the item lists for all of our 2008 invoices for sales commissions to be properly calculated. We have verified that this fixes the aforementioned issue. However, I have to wonder what would happen if an invoice ONLY had markup or discount items on it. Sure, you can argue "why on earth would you not have a service or inventory item on your invoice??" Then I would slap you and remind you that it's the principle.