Wednesday, November 14, 2012

Dojo DataGrid with Select Widget Formatter (Options)

I ran into quite a nasty issue today.

I have a dojo DataGrid I'm using to get user entry.  One of the fields was a text field, but my customer asked for it to be a drop down (Select) instead.  It was easy to add the select to the grid using the formatter option like this:


_layout.unshift({
'name' : 'Car',
'field' : 'car',
'editable' : false,
'width' : '65px',
'formatter' : _makeSelect
});
_editGrid = new dojox.grid.DataGrid({
singleClickEdit : true,
store : _editGridStore,
structure : _layout
});

The _layout has more fields, but you get the idea.  Then I created a _makeSelect function like this:


var _makeSelect = function(data, index, cell) {
var select = new dijit.form.Select({
           options: _cars,
           value: data,
       });
select._destroyOnRemove=true;
return select;
};


OK.  Take note of the options.  I'm using an array (_cars) of label/value objects that I set up earlier.  Each row in the grid will get this same options object.

I started having an issue where changing a value in one of the selects, would change the value in any other select that I clicked on!  It was driving me crazy!  I used a reductive process to start removing code until I came up with a small example/test file that I could reproduce the test with.  I ended up reproducing the issue/problem with only 2 Selects and no DataGrid at all.  See the problem was that I was using the same object for the options.  The dojo Select widget does not copy the options, but just takes what you give it.  (Google js references).  I have not fixed my code yet, but even if I was to use slice to copy my array, the objects (label/value) in the array would NOT get copied.  The object reference would get copied, so it would be a reference to an object in a DIFFERENT array!

Morale: Always give a unique options object to a dijit Select.  Stay sane!

PS: Could dojo "fix" this?  Maybe...

Monday, November 5, 2012

Dojo widgets always have a dom node

I am making a DataGrid with one column being a file upload column.

I was running into issues with this code because of a bad assumption on my part.  I thought the Form would not get added to the dom right away and it would not have a domNode until it was added to the page somewhere as a child.  That's not the case.  Once you construct a dijit, it has a domNode, although it may be "disconnected".  The reason I am not adding the Form to a domNode right away is that I am returning it and using it as the widget in a DataGrid using the formatter attribute.



var _form = new dijit.form.Form({
method : 'post',
enctype : 'multipart/form-data',
class : 'Uploader'
});
var _uploader = new dojox.form.Uploader(_dojoUploaderArgs);
_uploader.placeAt(_form.domNode);
_uploader._destroyOnRemove = true;

var _fileList = new dojox.form.uploader.FileList({
uploader : _uploader
});
_fileList.placeAt(_form.domNode);
_fileList._destroyOnRemove = true;

var _button = new dijit.form.Button({
type : 'submit',
label : 'Upload',
onClick : function() {
_uploader.upload();
}
});
_button.placeAt(_form.domNode);
_button._destroyOnRemove = true;

_button.startup();
_uploader.startup();
_fileList.startup();

Wednesday, October 17, 2012

.cvsignore

Why am I using CVS?  Good question.  Because everyone else in my team is using it.

Why is there a .cvsignore file with contents of:

target
and I have a target directory and it is NOT being ignored.  (Eclipse keeps wanting to check it in when I commit.)

Solution: Look around for other .cvsignore files.  CVS update your code.  Maybe there is a cvsignore file you don't know about.  Anyway there was a .cvsignore inside the target directory and that cvsignore file was checked into CVS.  Therefore the outer cvsignore file which was trying to ignore target CANNOT!

So I deleted the outer cvsignore file and committed.  I seem to remember that there were some resources in the target folder that DID want to be in CVS.  Maybe?

Looking at some git projects I am also a team member on, the .gitignore file always seems to be at the root of the project.  Kinda nice.  Put it all in one place.

Monday, October 8, 2012

Performance

Many things are important to consider when developing software. For example maintainability, robustness, quality, convention et cetera. One thing I have discovered as I have been developing software for many years is that performance is really critical. Slow and inefficient software has such a negative effect on user experience. This is especially true in the web and mobile world. You want to attract many, many users to your site or application, but if it starts to perform poorly with a large volume of users you have lost one of your main goals.

So next time you start hacking out a for loop, consider how many objects/records you could possibly be iterating over... It might be many more than you expect!

Friday, August 31, 2012

When to use Static Classes


I recently read this post about static classes and when to use them.  I found it a very useful and persuasive read.  Also it is good to know "why" to use object oriented code and not just blindly default to that design pattern.

It is for C#, but is applies to any language IMO.  Here static classes/methods can also be meant to be "functional" programming.

This was educational to me, so I'm sharing the wealth.

PS: I am still going to use static classes like String.trim() where there is no member data (stateless), and the functionality is VERY well defined and not likely to change.

Wednesday, August 29, 2012

Perl Parentheses

Oh man,

In Perl, you use () to declare a list like this:

my @array = (0);
my %hash = ('name' => 'Arvid');

Then when you want to access you have to use [] or {}:

my $array_val = $array[0];
my $name = $hash{'name'};

Just nutty syntax folks.

Tuesday, August 28, 2012

Problem with Getopt::Euclid and Empty @ARGV

Today I was working on a pl program that had some existing code using @ARGV. It worked. Then I added:

use Getopt::Euclid;

I was mystified to find out that the code did not work anymore. I did a little RTFM and found that Euclid will populate %ARGV instead of @ARGV. Fun! It makes perfect sense for Euclid to use a hash, but I was confused for a few minutes...

Why did the code compile with array access to a hash?? Because it's Perl!!!

Edit: After more work and more troubleshooting, the ARGV thing is clearing up.  We have a lot of existing code that uses %ARGV and @ARGV.  Sometimes it easier to access all the elements of an array instead of a hash.  This code used to work.  Now it is broken since I upgraded Getopt::Euclid.  In a certain release of Getopt::Euclid the developer decided to empty out @ARGV.  This is documented in the Euclid pod.  Now the question is, "What do I do with all that existing code using @ARGV?"

I've got some ideas.  One easy, but maybe kind of lame solution is to put a wrapper around Getopt::Euclid and save off @ARGV and reset it after Euclid is done.  Or I guess I could change the code.  More research is required.

Monday, August 27, 2012

Perl At Underscore

So I am doing some work taking a lot of boilerplate code and moving it into a static or class subroutine.  And when I say boilerplate, I mean boilerplate to the extreme.  I'd say 99% of the subs in this code base have the same kind of code at the beginning.  (Function entry logging, arg counting, arg hash key verification, validation that $self is a ref)

One thing I learned along the way:

$self or (this in java) is not implicit in a Class like it is in java.  That means if you call a method from Class a within Class a, you still need to prefix it with $self->method().

Hmmmmmmmmmm.

See also http://www.netalive.org/tinkering/serious-perl/.

One other thing.  I ended up sending @_ to my new sub as a reference like this \@_.

Wednesday, August 15, 2012

Behavior Driven Development (Again)

Today I have been rocking the regression test world.  I made 18 regression tests using Selenium.  That's 3 suites and one "master" suite.  Now I will feel a bit more comfortable doing re-factoring in my web app.

Tomorrow, I may do some JUnit... oh wait - I'm on vacation!  :D

Friday, June 22, 2012

Javascript Spreadsheet

I want to use one of these in a web app.  It just seems like a pretty cool UI for LOTS of people that are really good at excel.

dhtmlxSpreadsheet

jqGrid

Tuesday, May 22, 2012

Cross Domain Resource Sharing

There are lots of ways to do cross domain resource sharing.  Here are the 2 most popular.

JSONP
http://en.wikipedia.org/wiki/JSONP
  • Requires the server to "wrap" the json in a function call.


CORS
https://developer.mozilla.org/en/http_access_control
  • Better security
  • More modern
  • Requires an Access-Control-Allow-Origin string in the response header from the server.

Proxy / Server Wrapper
  • If you want to set up a proxy, go ahead
  • Or you can create your own REST service which in turn calls the resource you want.

Monday, May 21, 2012

Maven WAS RSA Dynamic Web Project Issue!

I was getting a 403 when trying to access my Dynamic Web Project in RSA.

I tried to add myself using the WebSphere Admin Console to the user mapping, but I was getting this error.

java.util.zip.ZipException: duplicate entry: META-INF/maven/com.ibm.mskhouse/DAO_MASK01/pom.xml

I took a step back and looked at application.xml from my WAS7 Test env.  It had a different security-role id, so I made it the same as the known good version and Voila!  The 403 is gone.

I also found that "Minimize application files copied to the server" is a good option to uncheck so that you can see all the files WAS is using for the hot deploy.

Thursday, May 17, 2012

Caching Service Requests

This guy is awesome: http://odino.org/rest-better-http-cache/.  I especially like the part where he's like, Application Cache?  WTF?  I worked on an application that had a really good built in application cache, but it does make you wonder why we always try to reinvent the wheel.

Friday, May 11, 2012

Oh Baby Oh How my Business did Grow - dojo.DeferredList


Oh baby oh!

Wow, so I was about to develop a REST service that gives me json for a drop down list.  But I have 4 lists coming from 4 database tables.  I was debating with myself... should I make 1 service or 4?  I need other data too.  Maybe I should lump it all together in one big web service?  Then I was thinking of reuse... that service is not very reusable.  If I made a service for each list, I could use them in other situations.  OK cool.  Then I start thinking of the code.  In one app I made in the past, I chained the REST calls and even made an object that would handle the chaining and callbacks for me.  Looking back, that was a big mistake.  Why?

dojo.DeferredList, that's why.


I did a quick google search for dojo chain xhrget requests.  DeferredList is the 3rd hit.  So it turns out that instead of calling 4 REST services in series, you can call them in parallel!  Dude if I'm late to the party, sorry, but this just blew my mind.  In other words, if the services take 400 ms, 300 ms, 500 ms and 200 ms to execute when called by themselves, instead of chaining them together and waiting 1.4 seconds, you get the results in 500ms.  Beautiful!

Friday, March 30, 2012

Creating Files in a Full File System (Unix, Linux)

I'm writing a program that has to be very fault tolerant.  I really need to create a file even if the file system is full.  I've always been able to create a zero byte file in this situation, but I never knew you could actually write output to that file (if you stay under a certain threshold)...

http://www.miek.nl/s/09f7401624/

Cool!

Monday, March 5, 2012

Online SQL Formatter

This is a really fun way to format and view an 1,800 character long SQL statement.  You go to the "Instant SQL Formatter", paste in your one long line of unreadable SQL, hit a button and get really nicely formatted output.  Thanks dpriver!

Tuesday, February 14, 2012

Perl DBD::DB2 DBI - So fun?

So I have some perl scripts written by someone else, targeted for AIX and I need to get them running on Linux 2.6.  Little did I know how much fun I would have.  I started having so much fun I decided to document it.  Really because if I was asked to do it again, I do not want to go through so much fun all over again!  Ha!  I should also mention that googling will get you the answers, but not all in one place.

Caveat:  I don't want to port these scripts.  I want to keep them as is as much as possible.

This is what the script does at one point:

$dbh = DBI->connect('DBD:DB2:db2_alias','user','pwd');

So the DBI / DB2 stuff was installed on AIX.  I need to install it on Linux to make this work.

Note About DB2 Client

Note the DB2 (IBM Data Server) has more than one type of client and it matters how you install it.  There is a bare bones "Runtime Client" and just a "Client".  The Runtime client does not have all the cool stuff like c/c++ include headers and nice config wizards.  I prefer the normal Client and installing it with all of the advanced features like the c/c++ libraries.

Step 1
Download DB2 Client for Linux 64.  You could try to use the cpan command to install DBI and DBD::DB2 first, but that would just tell you that you need the DB2 Client as a prereq.  You might get an error that it cannot find sqlcli.h.  (Not that I did this... ;)  Do not download the "Runtime Client" (RTCL) - download the "Client" (CLIENT).  I installed in the standard location, /opt/ibm/db2/V9.1.3.  Make sure you have the correct permissions on the files, folders.

Step 2
Use the perl cpan command (as root) to install DBD::DB2 like so.

cpan DBD::DB2


Say yes a few times and watch the madness of cpan.  It looks like the matrix to me.  Make sure your permissions are correct on the DB2.pm, Constants.pm, and do a find for Constants.so to make sure the permissions are ok on that too.  (I confess I did a chmod -R to get everything the way I wanted it).

Step 3
Sorry, but this is getting a bit foggy.  I've been through so many failed iterations, it's hard to remember what actually worked.  I think I downloaded DBD-DB2-1.82.tar.gz from cpan.  I think I used wget to get it right from linux.  Then I did a tar -xzvf DBD-DB2-1.82.tar.gz.  Then I did this:

perl Makefile.PL
make
make test
make install

Step 4
Now if you run a perl script that does the DBI->connect, you will get an error like, "Total environment allocation failure."  I like that error message.  Ha!
You need to create a user, catalog a database, etc. whatever.
Create a user with a new group.  The setup does not like it when you have the user in a group like "user".

sudo su - root
/usr/sbin/useradd -c DB2_Linux_User -d /home/db2lnx -m -g group some_group db2lnx
passwd db2lnx
exit # from root shell
su - db2lnx # to test the login and home dir.

Your commands may look quite a bit different depending on your security concerns.  I also had to add my user to a /etc/user.permits file.

Step 5
Go to /opt/ibm/db2/V9.1.3/instance and run db2isetup.  It's a nice wizard.  You already created the user, so choose the options to create a new database connection with an existing user.  Mine was successful, but it had one error saying it failed to do the db2icrt, which I want to think stands for Instance CReaTe.

Step 6
Run db2icrt.  If your user is messed up, you will get errors like: "DBI1088E Invalid access permission detected for directory /home/db2lnx".  A successful run will look like this:

$ sudo ./db2icrt tprslnx
DBI1070I Program db2icrt completed successfully.

Now you will have a /home/db2lnx/sqllib folder.

Step 7
Catalog the node and instance.  I'm assuming you have an existing DB2 database to connect to.  Follow the commands to catalog the node and catalog the database.  Then test the database.  Here is what I did:

login db2lnx
source /home/db2lnx/sqllib/db2profile
db2
catalog tcpip node abc remote abc.domain.com server 8080
DB20000I The CATALOG TCPIP NODE command completed successfully.
catalog database DBNAME as DBALIAS at node abc 
connect to DBALIAS user userid 
SQL8002N An attempt to connect to a host failed due to a missing DB2 Connect product or invalid license. SQLSTATE=42968

I found out later that db2ca is much easier to use than this command line tool.

Step 8
Obtain a license for the DB2 product.  You need a db2*.lic file.  Register the license file:

sudo /opt/ibm/db2/V9.1.3/db2licm -a /blah/db2/license/db2consv_ee.lic

If you try to connect and type the password wrong, you get this:


db2 => connect to db2mfg user cldb2
Enter current password for cldb2:
SQL30082N  Security processing failed with reason "15" ("PROCESSING FAILURE").
SQLSTATE=08001

If you use the CORRECT password, you get this:


   Database Connection Information

 Database server        = DB2 OS/blah version
 SQL authorization ID   = user
 Local database alias   = DBALIAS

db2 => quit

Step 9
Your perl script still may not work.  Make sure you have the correct instance set up like this.  Also make sure you run your db2profile.


$ENV{DB2INSTANCE} = "tprslnx";

Now my perl script works.  Thank goodness!

At one point I got this error trying to run the db2 command, but I can't remember which step it was. SQL10007N Message "-1390" could not be retrieved. Reason code: "3".

Follow up

Some stuff I've learned since.  Don't forget to run the db2profile before you run any of the db2 commands.

. /home/db2user/sqllib/db2profile.

Also, db2ca is an awesome tool for setting up database connections.  You may find it in /opt/IBM/db2/V9.7/instance.  A cool idea is to open db2ca on one machine, export all the database config data and import the config data on another machine.  It saves a lot of time trying to input all the database connection data for several databases.

See also my question about getting node.js connected to DB2.  Fun times!


Tuesday, January 31, 2012

Same origin policy

I have been fighting the same origin policy too much today.  This article from wikipedia sums it up really well.  I'm really surprised in all the googling I've done that not many people mention document.domain.  I've seen document.domain before, but I have not run into it in a while and forgot!

I've tried iframes, AJAX, code behind, and even looked at the proxy solution.  I still don't have a great solution, but I think I may try to implement the document.domain solution.  The problem is I will have to go edit potentially thousands of existing HTML files to add it.  I suppose I can script it.

One other thing that prevented code-behind from working is that it's an https connection with an invalid security certificate.  I should also mention that this is all internal intranet stuff.

If you google document.domain, the one thing you may miss is that even if you set the same document.domain on different files, the protocol matters.  That means they both need to be http or https.  No mix and match.

Thursday, January 26, 2012

Tuesday, January 17, 2012

Javascript Delete

Wow.  I don't have time to read this article about javascript delete, but I need to go back to it.

Read dojo source for better design

Quick note.  Thanks @dojo for being open source!  I've been learning a lot of good style from reading the source.

Tutorial 1 - HTML5

So I found this random guy at the new boston who does training videos.  The videos are pretty informal, but they are nice and short.  I did a few of his HTML5 tutorials.

Also I took a look at this sweet pure HTML5 app which works on the ipad and the net.

Then HTML5 graceful degradation.

I think I have only scratched the surface.

My New Years Resolution

My New Years resolution this year is two fold.

1. Ask more questions and be an attentive listener.  I've gotten good at tuning things out.  (Think long conference calls where you are pretty much listen only)

2.  Tutorials.  This is the big one.  I am going to do a tutorial every other week.  Not CREATE a tutorial on this blog, but go find one and do it.  Things I want to get better at:

  1. HTML5
  2. Spring
  3. AJAX
  4. REST
  5. CouchDB
  6. Ruby on Rails
  7. Java
  8. Eclipse
  9. Groovy Grails
  10. Hibernate
  11. Aspect J, JSPX
  12. I'm sure there is other stuff ... I'll come back and update this list.

Monday, January 9, 2012

Ssh Passwordless Authentication

I got this to work today.  I had an issue using the same "local" user ID on both systems.  I think ssh must have gotten confused at to which lilly-boy I was talking about.  Anyway, it worked great with different user ID's which is what I was going to do for prod anyway:

http://www.freebsdwiki.net/index.php/Ssh,_passwordless_authentication

Thursday, January 5, 2012

Dojo 1.7 / ADM / Performance

This is really nice.  I have been using dojo 1.6 for 6 months now.  I'm not using a CDN, so I'm serving the dojo toolkit from my web server.  It's a really small project, so I never set up a "build", but with dojo 1.7, I don't think I will need to.  The new AMD Loader will only load the dojo code that I need.  Sweet.  And it manages name conflicts so you can easily use other javascript frameworks.  Nice.

EDIT: I've now ported my project pretty easily to dojo 1.7 using a CDN.  Now I'm trying to use the define and require syntax to make my modules work with asynchronous modules (ADM).  I'm also using namespace.js, but I don't know if it is really needed now.

EDIT 2:  I had some "global" style javascript functions and variables.  Now I have converted everything to ADM.  There was some good re-factoring going on.  I still have some tightly coupled modules, but at least most of my modules are self contained and reusable.  So the re-factoring for dojo 1.7 ADM loader was nice, but I did not get the performance gains I was expecting.  I am now looking at downloading the SDK and doing a build to minify/concat to get better performance.

I ripped out namespace.js.  I didn't see a need for it anymore with the ADM modules.  Also I should note that the port to dojo 1.7 was easy.  The port to ADM loader was not, but I have much more OO code now which is good.