After returning from early-morning errand, created new MCRelat.java to create that table if it didn't exist, and called it from the Setup utility thereby finishing that, at 12:12. Starting to implement logout function ... quick cross-circuit from Loginout.logout to ActiveUsers.makeInactive done at 12:23, next to call this from DispatcherServlet ... need nap at 12:32. After nap and another errand, resuming work on logout function at 15:59 ... I got the code written so it'd compile, but I didn't have time to test it even once before uploading the files and then running to catch the bus to class, which I missed, forcing me to take another bus 15 minutes later, causing me to be 15 minutes late for the class. (Did anybody notice I was late tonight May.31?) After class, in the lab, I downloaded the files and tried the Setup program: The windows system properties weren't set up yet, so I had to copy them from the Setup output to the properties file. Then I discovered that backslant in a properties file isn't treated as a regular character, but instead combines with the next character, so I needed to change all backslant to two copies of backslant. Then that part of Setup worked. The next problem was that the routine to create tables in the database was reporting that the CREATE TABLE ... command had failed, because the return code from my wrapper around executUpdate was apparently catching a SQL exception and returning -1 to the caller. But in fact MicroSoft ACCESS was violating the API by returning -1 instead of 0 in that case. So I had to change my code to notice the -1 and change it to 0. Then that part to the end of Setup worked perfectly! Then I tried Top1 which is the NULL toplevel test rig just for the starting case where it gives me a login form, and it worked, including converting to swing. I didn't have with me the file of test data, so next I went directly to the TomCat server. The login form came up fine, but when I filled it out with correct info and submitted it, the server wouldn't accept the connection, because whereas the port number is 8000 on Linux, it's 8080 on Windows, so whereas the URL that I manually composed by modifying the sample-program URL was correct, the URLs generated by the program itself for action upon submitting a form was still the Linux URL. So I fixed the port number in the URLs in the program, but then it gave me file not found, because I needed to fix the path to the servlet also. After I did that, it worked, giving me the main screen showing options (send message, show report, and log out). Unfortunately I got servlet exceptions when I tested invalid login, and when I tested logout. Then I checked the time and noticed I had only 10 minutes left before I had to catch the bus home (or miss that bus and have to stay more than an hour later for the next bus), so I didn't have time for any more testing or even for e-mailing myself the changed files so that I could merge the changes with the master files on my laptop. It's now June.01 day-time. Just after 7 AM I woke up and since last night at class the instructor started talking about EJBs and asked me about my experience with them way back in early April, which was a long time ago, nearly two months ago, I decided this morning to check if the EJB application ConverterApp.ear was still around, yes it was, and to look around in it to see what parts it has, which took more than an hour before I just gave up because it takes 5-10 minutes for the screen to be updated almost every time I click on a new tab within deploytool. Finally after giving up looking around, I deployed the application, which took about ten minutes. Then I tried the Web client: It took a very long time to start up, but it worked again, using the original code before I changed the exchange rates in the source and compiled version. Then I tried the application client. The names of two files on the disk didn't start with the same case as the corresponding names in the command I copied and pasted, so I renamed the two files to match the command (actually one file specifically mentionned in the command, and the other just so all files would have the same-case first letter): $ mv converterApp.ear ConverterApp.ear $ mv converterAppClient.jar ConverterAppClient.jar $ ls Converter.java ConverterAppClient.jar ConverterClient.java index.jsp ConverterApp.ear ConverterBean.java ConverterHome.java index.txt Then when I re-tried the command, this happened: runclient -client ConverterApp.ear -name ConverterClient -textauth Initiating login ... Username = null Enter Username:guest Enter Password:guest123 Binding name:`java:comp/env/SimpleConverter` Caught an unexpected exception! javax.naming.NameNotFoundException <> Unbinding name:`java:comp/env/SimpleConverter` I have no idea how to find out what name was not found, I thought maybe there was an internal reference from one of the files or naming authority to that mis-capitalized file, so it needed to be different from the other files, so I renamed it back: $ mv ConverterAppClient.jar converterAppClient.jar Then I retried the runclient command, but got exactly the same error as before. I give up. Time now 09:09, appx. two hours burned on this worthless exercise. Back to work on Lab#3, specifically trying to remember the changes I needed to make on campus last night to make the program slightly work on the lab's computer. Put dummy fields in properties file until I can get the real info on campus (put the os.name and java.version as best I can remember, and put real junk for java.io.tmpdir) ... done at 09:13. Copied mainUrl from DispatcherServlet.java to lab3.properties under name linux.mainurl, and made dummy entry for windows.mainurl as best I can remember it. Made new method in Lab3Props.java called getMainUrl which simply fetches that property (per correct environment linux or windows) and returns it. Added a unit-test for that new method in main. Compiled and ran test, works, at 9:23. Edited DispatcherServlet.java to call that in the four places where appropriate, but felt totally drowsy at 09:27 and had to take nap. After nap and errands, now 14:16, got that working, then debugged the logout feature and got that working, now implementing next use case of presenting menu of cabs as checkboxes and allowing user to send message, at 15:48 ... at 15:56 I absolutely needed another nap immediately, finished at 17:28 and resuming work ... finished writing code in Cabs.java to return vector of vector-pairs [cabID#, cabName] and test rig showing it works at 17:42. Next to call that from servlet to build sequence of checkboxes ... wrote routine in ClientWriter to build a checkbox structure, and tested it, done at 18:59. Upgraded ClientWriter.toHtml to handle case of checkboxes, done and tested and working at 19:37. I'll skip conversion to swing for the moment. Added new feature to unwrapper (for NULL mode) where the HTML can be written to a file on temporary directory, whereupon I can have a Web browser looking at that file and simply re-load the page whenever I want to see the latest version of HTML overwritten there. So using that new feature and lynx to view it, I've verified the form listing all the taxicabs as checkboxes and with a place to compose message text is working, as of 22:05. (If I had thought of this idea a couple weeks ago, I wouldn't have needed to implement conversion to swing at all as a debugging tool.) Next, at 22:24, to write code to take the result of filling out that form and actually (pretend to) send messages and register them in the database ... First I needed to implement multiple values for the same tag, to handle multiple checkboxes all with the same name but with different values. Most of the code is written but it's bedtime so I won't be able to finish it until morning. Now 23:56. It's now 2005.Jun.02 at 08:18, starting to write unit-test for the code I wrote just before bedtime last night. Wrote function to print out entire contents of HashMap in legible form. Also included decoding of MIME-coded-form-contents for each tag and value extracted from tag=val&tag=val&... string. Tested and working at 09:31. Next, starting to write code to use all that to process the submitted send-message form ... completed code in MCRelat.java to add relationship record, tested working at 10:46. Next, starting to write new file DBUtil.java per specs in dj3dbutil.txt, starting with sendMessage(...) ... got code working and tested as of 12:08 but need to turn off verbose trace output ... done at 12:23. Next to call that from the servlet ... done but bitten by apostrophe in the text of my message which broke SQL update command. Tried putting \ before the ' but SQL doesn't recognize that convention. Finally I gave up and re-worded to say "do not" instead of "don't" and it worked. It's now 12:58. Need some code cleanup ... done at 13:28. Now working on showing report of last N messages ... got business logic working in DBUtil as of 14:49, now to reduce trace output and call from servlet ... done at 15:21. Next to put in the button to take user to menu screen again ... all working (in NULL test rig) as of 15:44. Next to startup J2EE server and do a live test ... copied files, server up at 16:03. Ready to try live test ... gave up at 16:09 when server still hadn't put up first Web page, already had no nap and need shower and late for class and still need to upload files ... so what I did was to initiate stoppage of J2EE server and take shower while it was stopping, then initiate stoppage of cloudscape and dry while it was stopping, then rush to collect and zip and uuencode and upload the latest files, not bothering to uudecode or e-mail them yet, then quickly log out and shut down Linux while getting dressed to catch the bus, to arrive only 2 minutes after the start of class but the instructor had already started talking. After class, in the lab, I TELNETted to my shell account to uudecode what I had uploaded then e-mail to my Yahoo! Mail account, then log into my Yahoo! Mail account to download the zip and then unzip it, then reconciled the original and modified versions of Tuesday's files to see what changes had been needed to make the earlier version work on Windows, then folded those changes into the new files from Linux. Before testing anything, I e-mailed from my Yahoo! Mail account attachments of all the files that had changed, so that later I would be able to reconcile them on Linux and finally have a standard version of the files that would be the same on both systems. Then I established the MicroSoft ACCESS data source, ran Setup, then ran the NULL test loop briefly to see if things worked at all, they did. The started TomCat server and tried the servlet: It worked!! Today, Friday Jun.03, I finally tried downloading BeanShell via Unix and dialup modem to my laptop, and tried running it here in special-window mode: It worked, although copy&paste with emacs or X window don't work, although copy&paste with gNotePad and gEdit does work, so if I need to copy text between the two environments I can save text to a file from one envrironment and then load that file with an editor in the other environment and copy from there, a big pain for snippets of code but tolerable if I need to copy a large chunk of code across. Also if I run a program that does terminal I/O, it's all confused because BeanShell is doing I/O in the special window while the program it's running is doing I/O in the X window from which I started BeanShell, and it's difficult to know where to type anything and how to abort anything. Then I tried running BeanShell terminal-mode on my shell account on Unix ISP: It bombs immediately at start-up: Exception in thread "main" bsh.InterpreterError: internal error 1 in This: java.lang.ClassNotFoundException: bsh.JThis at bsh.This.getThis(Unknown Source) Then I tried running BeanShell terminal-mode on my laptop: It works! And of course copy&paste between emace and terminal-mode in X terminal works the same as always. As a real test, I copied individual lines of code from a swing application from the previous Java class to emacs, edited them there, then copied individual modified lines of code to BeanShell terminal-mode, and as a result I'm sitting here with a JFrame visible on-screen. So it seems I can use BeanShell for LISP-REP-style development for real if I want. So I'm going to try future bottom-up tool-building development of the current Distributed-Java Lab#3 project using BeanShell to avoid having to wait a full minute or so every time I want to test one or two new lines of code, running a compile cycle only when really necessary. But first, I'm totally exhausted from no-nap-yesterday, so I needed to take a long nap mid-day. It's now 17:14 as I start using BeanShell for continued work on Lab#3 taxicab messages. Starting work on use case #3 (display per-cab totals) ... at 19:38 I have the business logic finished and debugged in BeanShell for collecting all the data and returning a Vector of 3-Vectors each of form [CabID# CabName MsgsPerCab], and in the process I extended Sexpr1.toSexpr to handle int[] just as it already handled String[], and what a relief, never had to run javac once the whole time! Now at 19:40 to run javac on all the changes files to see if we (BeanShell and myself) missed anything javac would catch ... in Sexpr1 there were no compiler errors. In DBUtil there were a few minor errors such as where I changed the name of a variable halfway through development and was still referring to the old name from one place, and where I set up a variable in one method but failed to set it up in another method where it also was used. And then when I fixed those so that javac could compile more deeply, it discovered that I had failed to catch java.swl.SQLException every place I did something with a ResultSet. Fixing those, at 20:01 no more compiler errors. No need for more unit tests on that code until I write the one line of code in DispatcherServlet which calls the toplevel method of the new business logic and unit-test that one line of code as part of developing the servlet code. Starting work on on that servlet code ... aha, the first serious bug in BeanShell: The following line of code crashes BeanShell all the way out to terminate fatally out to the shell: bsh % wrReq = HSA.wrapRequest(objReq); Exception in thread "main" java.lang.NoClassDefFoundError: javax/servlet/ServletResponse at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:195) at bsh.classpath.ClassManagerImpl.classForName(Unknown Source) at bsh.NameSpace.classForName(Unknown Source) at bsh.NameSpace.getClassImpl(Unknown Source) at bsh.NameSpace.getClass(Unknown Source) ... So when that happens, I lose my BeanShell entirely, and need to fix the problem then re-start the BeanShell. I think the problem was that it needs the j2ee.jar included in classpath. I'll do that and try again at 20:34 ... yes, that fixed the problem. Continuing work at 20:41 ... OK, I've gotten to that one line of code that unit-tests all that I was working on before, but now in javac compiled form: bsh % v = DBUtil.getPercabNamesTotals(); <[[1, Johnny, 4], [2, Mikey, 7], [3, Janice, 8], [4, Monica, 1], [5, Judy, 8], [6, Murphy, 4]]> and of course it works just as well now as it did when the pieces were built by BeanShell. Continuing at 20:45 ... now I need to write code to generate multi-UI structure for a table, but first I'll manually build a very small table just to make sure lynx renders it correctly built, checking in lynx now ... no good, lynx doesn't bother to line up columns whatsoever: Name Relationship Location Robert (self) Sunnyvale Heather Beloved (unknown) Elton Father Oregon so I tried it in Netscape, and it worked correctly, but when I copy from Netscape and paste here, I get this nicely-lined-up mess: Name Relationship Location Robert (self) Sunnyvale Heather Beloved (unknown) Elton Father Oregon Anyway, now that I know that I know how to do tables correctly, and that Netscape is rendering them correctly so I can see if my software generates them correctly, I can proceed with the code, at 20:59 ... at 21:46 I'm getting a strange exception I didn't get when I did the same thing before: java.sql.SQLException: no such object in table This is when I repeat the query: SELECT max(CabID) FROM Cabs which works just fine when I re-do it manually in cloudscape -isql, but repeatedly fails when I re-do it from my program code. Hmm, when I re-run the Setup program, it claims that table Cabs doesn't exist, and when it tries to create the table it gets that same exception as above. I tentatively conclude the connection to cloudscape is in a funny state, or cloudscape itself is in a funny state. Let me try the setup program directly from the shell ... it says everything is fine, all tables exist and expected number of records in each, agreeing with cloudscape -isql. Next thing to try is to kill BeanShell and re-start it, but first I tried to kill cloudscape -isql whereupon it gave me that same strange error. Continuing to kill BeanShell ... done, restarted and ran Setup with no problem, re-ran the method-call where it failed before and now it works, re-defining the last method I did before it died, re-running that method-call again where it failed and now it works, finally running for the very first time the unit test of that new method ... it works, giving the multi-UI structured object representing a FORM: ("TABLE" ("ROW" <1> "Johnny" <4>) ("ROW" <2> "Mikey" <7>) ("ROW" <3> "Janice" <8>) ("ROW" <4> "Monica" <1>) ("ROW" <5> "Judy" <8>) ("ROW" <6> "Murphy" <4>)) Next at 22:08 to write code to convert that to HTML but first a break ... but too tired to do anything except use the last bit of my energy to wash some dishes then go to bed. But can't sleep, so at 01:29 resuming work ... done unit-testing code for basic 3-column table at 02:39, now to write code to convert to HTML and also include column headers in the original structure ... done in crude form at 03:12, next to incorporate into servlet so NULL test rig will write to test file ... at 03:17 I'm getting that "java.sql.SQLException: no such object in table" again. Time to re-start BeanShell, and while I'm at it I might as well re-compile sources which changed ... no compiler diagnostics in ClientWriter, and in DispatcherWriter only one method-call I prematurely activated before it was defined, and three undeclared variables, done at 03:31. Time to go to bed again, maybe for real this time. Now 2005.Jun.04 at 09:55 as I resume work on whatever I was working on in the middle of the night ... done putting pieces together so I could call the business logic then the unwrapper to write the HTML to /tmp/ file, and viewed in Netscape, and table looks correct as of 10:31. Next to finish putting the one toplevel call into the servlet file and compiling all changed files ... done at 10:38 (no compiler diagnostics), next to set up test data to invoke the new use case ... done, ran NULL-mode test rig, wrote /tmp/ file, looked at it in Netscape, looks fine! Next I need to include the button at the bottom for getting back to the main menu, and replace the column head for "Msg count" to be a button that sorts by that column ... but first I cleaned up the code by making sure there's a comment at the start of each method explaining briefly what its purpose is and what actions it performs, found method to build to-main-menu button, incorporating it now ... done, compiling ... done, running NULL-mode test ... done, wrote /tmp/ file, looked at in Netscape, looks perfect at 11:12. Before starting to implement column head to sort by #messages, I'm going to shut down cloudscape and emacs, shut down and restart Linux, restart cloudscape, and start J2EE server for first time since aborted attempt yesterday afternoon, first real time since a couple days ago, and run a *live* J2EE HttpServlet test, starting shutdowns at 11:15 ... Linux was fully down at 11:18 and starting back up ... oops I forgot to go into super-user mode before trying to start J2EE, so it died when it couldn't start JMS, so I had to re-start that part ... at 11:28 J2EE was up and I started bringing CloudScape up ... at 11:30 that's up, running Setup ... AOK, started up lynx and clicked on link to start servlet at 11:33, waiting for J2EE server to deliver the initial page ... ops, I forgot to copy the changed class files from my development directory to the system directory, doing that now just as server is offering cookie to lynx at 11:37 ... done at 11:43, now to try lynx ... accepted cookie at 11:45, filled out log-in form and submitted it at 11:46, waiting for server to process the form ... got main menu at 11:49, clicked on send-message button at 11:50, waiting for server to bring up send-message details form ... got form at 11:54, filled it out (send to Mikey and Monica) and submitted during same minute, waiting for server to confirm message sent and show last N messages ... got that at 12:00, clicked on main-menu button, got main menu quickly at 12:01, clicked on button to show msgstotals per cab at 12:02, waiting for response ... at 12:05 I got servlet exception from not-yet-implemented exception in yesterday's code, so it seems the server has cached the old code before today's changes, so at 12:06 I initiated J2EE shutdown ... at 12:15 I got first response from the two programs that they were shutting down service, at 12:17 shutdown finished and I invoked starting J2EE back up ... up at 12:22, started lynx, clicked on button to run servlet at 12:23, waiting for server to respond ... at 12:28 it offered cookie, I accepted cookie and filled out login form and submitted at 12:29, waiting for server response ... got already-logged-in warning and offer to attach to already-existing login session and main menu at 12:31, clicked button to show report of per-cab message totals (the new code of today), waiting for server to respond ... got report (bad format because I'm in lynx) at 12:37, clicked on button to return to main menu ... got main menu at 12:41, clicked log-out button ... at 12:44 it gave confirmation of logout and showed new log-in form, end of test. Conclusion: after debugging in BeanShell, module compiler diagnostics it worked perfect first time in NULL-mode test rig, and then with no further changes but an hour and a half of time it worked perfectly in live J2EE servlet-container session. Meta-conclusion: I wish I had thought of trying BeanShell a couple months ago, before this huge lab assignment started, so I could have used it the whole time, would have cut development of NULL-mode test rig to one week instead of two, but I'm glad I thought of it now. Now I'm going to shut down J2EE server and take a nap before starting coding of use case for clicking on column header to sort by contents of that column. After nap and washing dishes etc., at 15:03, and I'll split this log at this point and update the index file and upload both ...