It's now 2005.May.19 at 09:25, after cleaning up directories and playing with JTabbedPane a bit more than when I previously played with it on Dec.30, I'm now ready to start serious direct work on adapter for servlets. Earlier I was considering whether to write an adapter as an object that sits between the UI and the actual as-is HttpServlet, or whether to just modify the HttpServlet in-place. To allow the HttpServlet to operate under a swing test-rig, it'll have to be modified anyway to generate structured representation of HTML forms instead of spewing HTML syntax directly to request.out.println, so there's no point in trying to avoid modifying it, so there's no advantage to having the extra layer of adapter between the UI and the servlet. So I'm sticking with my original idea that each multi-UI-capable servlet must call convertRequest immediately upon entry to doGet or doPost, and must call convertResponse just before return. Also I'll have to make sure convertResponse is called in *all* cases, even when a fatal ServletException is thrown, so I'll have to define doPost to call doGet which will have a try block and a finally clause calling convertResponse. While writing prototype code below, the following dilemma occurred: Modify in-place, or put wrapper around request/response objects: Because the interfaces I'm going to define for watered down versions of HttpServletRequest/Response are defined *after* the system-defined classes they correspond to, hence compile-time checking of satifying the interface will be impossible when running under an actual J2EE servlet container, hence request/response objects must be declared as type Object, consequently instance methods won't work, because class Object doesn't have the methods defined so we can't call the instance methods directly from an Object object, but we can't down-cast Object to the interface because with a real live HttpServlet... object we'd get a bad-cast exception. So we have to use static methods for all such code, ugly! That's if the adapter simply modifies the HttpServlet... object in-place. But if we put a wrapper around the actual object, with that wrapper taking instance method calls and forwarding them to instance method calls on the embedded object, then *every* instance method of HttpServlet... that we plan to call from our servlet will need to be forwarded like that. But such methods will need to be defined in our test-rig objects anyway, so maybe a wrapper isn't such a bad idea after all. The wrapper can simply re-use the object if it already satisfies MyHttpServlet... interface for purpose of compiler, and put an actual wrapper around anything runtime-satisfying but not compiler-satisfying. Actually if we include extra methods, such as overloading print and println to take structured HTML-form objects, then we'll *always* need a wrapper because the native objects don't have such method signatures (except Object.print[ln] which definitely does the wrong thing). But if we're wrapping the request and response objects, then *both* must be explicitly wrapped upon entry to our servlet, so instead of calling convertRequest on entry and convertResponse on exit, we'll need to call wrapRequest and wrapResponse on entry and unwrapResponse on exit. Also, I'll need two sets of interfaces for each object: First a check that the Object passed to it really does satisfy the minimal requirements common to both system-supplied objects and my own fabricated objects: MinimalHttpServletRequest MinimalHttpServletResponse then the enhanced minimal wrappers actually used by the servlets, which support the usual syntax of instance-method calling, and compile-time verification that all such instance methods really do exist: MyHttpServletRequest MyHttpServletResponse So the overhead of runtime checking of class against interface will occur only once (for 3 classes) upon entry to the servlet, not every time a method is called from within the servlet. Yay, it sounds like a plan! So putting this all together, prototype servlet doGet looks like: public void doGet (Object req, // must satisfy HttpServletRequest Object resp // must satisfy MyHttpServletResponse ) throws ServletException, IOException { /* First do runtime check that Object req/resp really do satisfy the after-the-fact minimal interfaces I've devised, then put wrapper around each which allows compiletime checking of method calls using usual syntax wResp.method(args) etc. */ MyHttpServletRequest wReq = MyServletAdapter.wrapRequest(req); MyHttpServletResponse wResp = MyServletAdapter.wrapResponse(resp); wResp.setContentType(resp, "text/html"); wResp.setBufferSize(resp, 8192); try { doGetMain(wReq,wResp); } catch (Throwable ex) { ...emit-inline-error-report-text... } finally { MySerletAdapter.unwrapResponse(wResp); /* modifies embedded obj */ } } public void doGetMain (MyHttpServletRequest req, MyHttpServletResponse resp) throws ServletException, IOException { ...whatwould.normally.be.here } There are three cases within wrapRequest: -1- Given a system-supplied HttpServletRequest object -2- Given a test-rig or swing substitute of class MinimalHttpServletRequest =3- Given an already-wrapped object of class MyHttpServletRequest because this servlet got a control-transfer from another servlet. In that third case the parameter will be returned without change. The same logic applies to wrapResponse. Hopefully the two will match cases 1 2 or 3, but it's too hard to check for that so I won't. In all cases, some flag will be set in the wrapped response object to indicate what kind of UI is involved. For unwrapResponse, the kind-of-UI flag will be checked to see whether to convert structured forms into streaming HTML or into nested JPanels or into XML description. In all cases the embedded request object will be updated, either by calling println on its its printWriter to spew out HTML syntax, or setting a property within the embedded object to point to the nested JPanels or XML syntax to be recovered by the swing toplevel or debug rig respectively. So my plan of action is: - Define the two Minimal and two My interfaces needed, and test them against dummy classes and real online classes. - Modify the sample servlet to embed doGetMain inside doGet per above. - Write the wrapper and unwrapper methods and verify they don't break the already-working servlet - Make stdio test rig that sets up req/resp objects defined by me, and shows XML output of structured-form from response object upon return from servlet, and try to call the existing-modified sample servlet from the test rig. At 10:52 I'm checking back with May.12 to-do list to see if I forgot anything ... oh, before any of that, I need to follow the JSP that calls doGet from a servlet, modify that doGet method to print out useful data from the request object, the same info I printed directly from the JSP last night. I can't run that servlet directly from URL because of bugs in deploytool and/or J2EE server on Linux, but hopefully I'll be able to call it directly from my test rig after I modify it to include the wrapping and unwrapping specified above. Taking break at 11:00. Now 12:45, resuming work while laundry is drying. Laundry done and out. At 14:10 I have finished configuring the following, and all working so-far: - ShowJspEnv.jsp (copy of getstuff.jsp from last night with everything removed except initial check of session object from three sources (session variable in jsp, result from request.getsession(), result from request.getRequestedSessionId(), where we get two different session facades but all three IDs are equal as strings). - jump1.jsp sets up DispatcherServlet.class as a bean and calls the doGet method from it. Currently that is actually a copy of the greeting from sample program hello1 because that's the only servlet that works currently. Next I need to rename and modify DispatcherServlet.java to be ShowServletEnv.java but still have the original hello1 innerds, just to see if I can get it linked and working under that name, at 14:18 ... now 14:54 and I have it linked and apparently working, but since it displays exactly the same text as under the previous name, I can't be sure it hasn't cached what I had before, so now I'll change the text to prove it's getting the newly-compiled stuff ... done, but refresh just brings back the same text as before that change, because TomCat is caching the class file, need to shut down J2EE and re-start at 15:00 ... while it's shutting down, I don't know whether *all* classes called from JSPs are cached, or only the ones called as beans, such as this one ... 15:04 and it's still shutting down JMS service ... 15:05 it's finally finished shutting down and I'm having it restart again ... at 15:11 it's finally started again, total eleven minutes to shut down and restart, anyway, going to refresh Web page where jsp links to ShowServletEnv.class and see if it has purged the cache from before, 15:13 ... jsp recompiling because compiled version from before shutdown/restart no longer available ... ah at 15:14 the new text comes up! So it seems I need to shut down J2EE and restart every time I change anything in my code, although an alternate idea would be to change the name of file and name of class in file each time I recompile it and change the indirect vector in the jsp accordingly, which I'm sure would take less than 14 minutes from make-change to page-updated-on-screen. But that's too much hassle. Or not. I'm ambivalent about which very slow way is worst. Anyway, let me try the rename-file trick this time, and see how long it really takes. Renaming one file and editing several files at 15:18 ... edits done at 15:22, going to recompile and move now ... done at 15:27, refresh now ... success, the very latest code is on screen. Now 15:28, total time after edit done to refresh done is 6 min, total time including edit is 10 minutes. That's 5 minutes longer than recompiling non-J2EE applications, but 4 minutes faster than taking J2EE server down and back up, on the other hand those 4 minutes saved probably aren't worth the hassle of needing to rename one file (source of Servlet) and edit four files (source of servlet, command file to compile it, command file to move complied file from my area to system area, jsp to jump to different servlet). I think I'll just bring TomCat down and back up every time I change one line of code in my servlet. And work really hard to get my test rig working so I won't have to deal with J2EE serve at all during most of the development sessions. So now that I've decided that, I need to copy all the java code from ShowJspEnv.jsp to ShowServletEnv.java, recompile, shutdown/restart J2EE server, and see if it works just like the JSP did, showing me info about request and session objects ... done editing to make it compile at 15:50, and shutting down J2EE server now. While it's shutting down, let me share the two compiler errors I had to fix. First, session is pre-defined in jsp but not in servlet, so I had to declare it and fetch the value from the request object. But the class isn't automatically imported as it is in JSPs, so I needed to explicitly import it into the java source. But that's all it needed to compile successfully. At 15:53 I noticed the disk suddenly stopped thrashing, so I checked, and sure enough the shutdown of server was done, so I invoked restarting it again, but some parts of startup aren't very disk-thrashing, so right now it's quite even though it's just done the first listen port and hasn't even started starting up JMS yet ... at 16:00 it finished starting up, going to refresh again ... 16:02 and it works, and furthermore it gives interesting output: ** The request object --> org.apache.catalina.connector.HttpRequestFacade@4d659d ** The session object org.apache.catalina.session.StandardSessionFacade@4a3158 ** sess = request.getSession(false) --> org.apache.catalina.session.StandardSessionFacade@6d8eb5 session.getId(): 30C5F535887285341240A20823C1F851 sess.getId(): 30C5F535887285341240A20823C1F851 (They agree.) * rs = request.getRequestedSessionId() --> F839F343A00141D7A0B57035C4612555 (That request was not satisfied.) First, most obvious, the refresh used a cookie the browser still had from before the shutdown/restart, but that session is now expired because session IDs can't survive a shutdown/restart, so the server refused the request for the old session and made a new session instead. Second, more subtle: My code originally used the session object inherent in the JSP environment, and also got the session object from the request object, and showed them both, obviously not the same (in earlier transcript of JSP). But Servlet doesn't have session object already as local variable, so to make my code continue to work in servlet with minimal change, I simply got the session object from the request object an additional time before entering the old code which expected it to already exist. So now the two session objects should be identical. But do they look identical to you?? Here are the two relevant lines: org.apache.catalina.session.StandardSessionFacade@4a3158 --> org.apache.catalina.session.StandardSessionFacade@6d8eb5 Anyway, now to clean up that code to get the session object only once. ... edit and recompilation done at 16:21, now I'm going to start working on setting up the new interfaces for request and response objects, but first I'll stop/restart J2EE while I finish sorting socks ... done at 14:30, refreshing browser screen ... at 14:33 it's refreshed with new output just fine, now taking nap... At 19:30 I'm looking back through the typical calls from servlets which I collected in the May17 log file, pinning down what class each method is in. OK, done collecting the info at 20:34, moving it to individual file IntMethods.txt, done. Starting to write java source files for all the MinimalHttpServlet... and MyHttpServlet..., compiled them including FakeHttpServletRequest, realized I need MinimalSession and FakeSession too, so that FakeHttpServletRequest can make such a thing and later return it when asked getSession. Doing that now at 21:46 ... done, but then I decided to check e-mail and found I finally got a reply from Sukhjit about how to compile on campus lab, but info was incomplete so I had to ask a followup pair of questions. Back to Linux stuff: OK, done making the various Minimal... stuff including MinimalSession.java interface, and getting them to compile, now 23:00. Now copying them to system area where the servlet can find them ... oops, I just noticed I used the wrong name, MinimalSession should read MinimalHttpSession, will change that now ... done and class files copied into the same classes directory as the servlet itself. Hopefully if I try to call any of them directly from the servlet, the class loader will find them. Next to copy my utility for comparing a class against an interface to that same servlet classes directory ... OK, CompareIntCls.class copied there too, so now I'll be able to write code whereby my servlet checks classes against interfaces at runtime. Now before I install any of that in the servlet, I need to check one last thing: I need to change the declarations of parameters for request/response objects, each to just Object, but then immediately do a downcast to what they really are. That shouldn't break anything, if understand the way Java works. Editing the servlet code now at 23:22 ... done and compiled, moving class file to servlet classes directory ... done, now to refresh browser on the JSP that calls that modified doGet method ... nope, the old version is in the cache, now 23:37 and I've started to shutdown J2EE server ... and at 23:40 it's down and I'm starting it back up ... back up at 23:45, refreshing Web browser again, waiting for it to compile JSP first-time this server-up session ... what, it's *still* getting old content, why?? Looking at jump1.jsp next ... aha, last time I changed the name of the servlet I forgot to change the name of the reference to it in the jsp, fixed in jsp now, waiting for jsp to recompile again at 23:50 ... OK, at 23:53 I have my answer: No, it doesn't work to declare the parameters to doGet to be of type Object. Here's the servlet exception that comes on-screen: A Servlet Exception Has Occurred org.apache.jasper.JasperException: Unable to compile class for JSP An error occured between lines: 13 and 14 in the jsp file: /jump1.jsp Generated servlet error: /usr/java/j2sdkee1.3/repository/adsl-63-192-44-196.roadguy.com/web/date/_0002fj ump1_jsp.java:127: Reference to doGet is ambiguous. It is defined in void doGet (java.lang.Object, java.lang.Object) and void doGet(javax.servlet.http.HttpServ letRequest, javax.servlet.http.HttpServletResponse). srv.doGet(request, response); // **not** the way we should d o it!! ^ 1 error at org.apache.jasper.compiler.Compiler.compile(Compiler.java:284) at org.apache.jasper.servlet.JspServlet.loadJSP(JspServlet.java:528) at org.apache.jasper.servlet.JspServlet$JspServletWrapper.loadIfNecessa ry(JspServlet.java:176) at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspSe rvlet.java:188) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java: 381) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:458) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(App licationFilterChain.java:247) at org.apache.catalina.core.ApplicationFilterChain.access$0(Application FilterChain.java:197) at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFil terChain.java:176) at java.security.AccessController.doPrivileged(Native Method) at org.apache.catalina.core.ApplicationFilterChain.doFilter(Application FilterChain.java:172) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapper Valve.java:243) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.ja va:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943 ) at org.apache.catalina.core.StandardContextValve.invoke(StandardContext Valve.java:215) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:566) at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValv e.java:246) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.ja va:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943 ) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java :2314) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve. java:164) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:566) at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.j ava:368) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:564) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.ja va:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943 ) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVa lve.java:163) at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipelin e.java:566) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.ja va:472) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943 ) at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcess or.java:995) at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.j ava:1088) at java.lang.Thread.run(Thread.java:484) So just after midnight I have an idea how to fix this. Instead of forcing a single entry point for servlets, I'll use the standard entry point (with req/resp objects declared in usual way) *only* when actually coming through a live HTTP session, and in all adapted cases (stdio-test-rig, swing-toplevel, CGI-adapter) I'll come in through an alternate entry point where args are declared of type Minimal... or My..., so let me do that edit now and see if it works. Meanwhile, I figured out that since I know I'll have to stop and restart the J2EE server each time I change the servlet, I might as well start the shutdown/restart sequence while I'm doing editing of source and recompilation etc., long before I actually need the server back up with cache flushed, so then I won't actually lose any of *my* time waiting for the server-down/up sequence. I'll start shutdown right now Friday May.20 at 00:07 ... OK, shutdown in progress, now to edit the servlet entry point ... 00:10 server down and going back up while I'm in middle of edit ... server back up at 00:16 and I'm still in the edit, so I think this new idea is a good one, more editing ... done with edit at 00:20, compiling ... copied file, started refresh, now 00:27 as I wait for jsp to finish compiling ... it bombs with this error: java.lang.LinkageError: duplicate class definition: DispatcherServlet OK, I commented out the no-longer-used bean reference for that, refreshing, waiting for JSP to auto-compile, very very much in need of beddy-bye, hope this works, now 00:33 ... 00:35 it's back to working. Here's the current code at the top of doGet: public void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException { doGetAdapter(request,response); } public void doGetAdapter(Object reqO, Object respO) throws javax.servlet.ServletException { HttpServletRequest request = (HttpServletRequest)reqO; HttpServletResponse response = (HttpServletResponse)respO; After a night's sleep, I will need to write and install the wrappers and unwrapper as planned for a long time, the wrappers replacing the static downcast in those last two lines above, and the unwrapper happening in finally clause shortly down from there. It's now Friday day-time, specifically May.20 at 15:24. Earlier I was trying to develop the code for wrapping/unwrapping request/response objects using the servlet, but the prospect of 15-minute turnaround time for each tiny change, whereby I'd lose my train of thought each time and be totally lost, was making progress seem hopeless. But just now I came up with a new idea for debugging the code: The data-flow per se, i.e. how the request object for example comes in from the J2SE server (servlet container thereof) and goes through my code for wrapping and then gets processed by the servlet innerds and then goes through the unwrapper and then goes out to the client (browser), can be debugged completely in a JSP (scriptlet thereof) which has faster turnaround time than bringing the server down and back up. Then once I have the linear data-flow debugged, I can simply copy all that linear code into the proper structure in the servlet, and it should work without any further debugging cycles. In this way I can debug the wrapping of live HTTP servlet sessions in a way not much slower than debugging ordinary Java code. So I'm going to try that now. ... At 16:18 I realized I can optimize my time by working on the servlet/JSP environment (live HTTP session) and a non-servlet environment at the same time. The same code will exist in DataFlow.jsp (scriptlet) and DataFlow.java (inline), each calling exactly the same sequence of adapter utilities (those will check the mode, i.e. HTTP or NULL or SWING etc., and do different things in different modes, but the overall structure of the code will have exactly the same dataflow at the level of the DataFlow.jsp/java from which the adapter utilities get called). What I will do is write the new code in the jsp first, and start a browser refresh, which forces the jsp to compile, but while it's compiling I then copy the same new code into DataFlow.java and manually compile it and then whichever is finished compiling first I look at that output first. *** Something totally weird happened after I mistakenly tried to start j2ee without being in super-user mode and had to do a cleanup before trying to re-start it again: When I tried to save my edit of the jsp I had been working on, it claimed there was no such directory. Also, when I tried to do anything from an X window that had been connected to the WEB-INF/classes sub-directory of where the jsp was, in super-user mode, it acted totally weird: [root@adsl-63-192-44-196 classes]# pwd /usr/java/j2sdkee1.3/public_html/date/WEB-INF/classes (That looked correct, the grandparent directory .../date/ exists just fine.) [root@adsl-63-192-44-196 classes]# emacs emacs: `getcwd' failed: No such file or directory (That was totally weird!!) [root@adsl-63-192-44-196 classes]# pwd /usr/java/j2sdkee1.3/public_html/date/WEB-INF/classes [root@adsl-63-192-44-196 classes]# ls ../.. (That's clearly wrong! Two directories up, in .../date/, there should be a whole bunch of jsp files.) [root@adsl-63-192-44-196 classes]# pwd /usr/java/j2sdkee1.3/public_html/date/WEB-INF/classes [root@adsl-63-192-44-196 classes]# cd ../.. cd: could not get current directory cd: could not get current directory (Now that's really really weird!!) [root@adsl-63-192-44-196 .]# pwd pwd: could not get current directory (And that's awful too!!) [root@adsl-63-192-44-196 .]# cd / cd_links: could not get current directory (Oh oh, now I was beginning to fear the root directory had somehow become dismounted, which would make my computer unusable!!) So I took a chance and opened another X-term window, and did this: [rem@adsl-63-192-44-196 rem]$ pwd /home/rem [rem@adsl-63-192-44-196 rem]$ su Password: [root@adsl-63-192-44-196 rem]# cd /usr/java/*3/p* (That should get me back to the public_html directory, which contains all the single-application directories such as .../date/, right?) [root@adsl-63-192-44-196 public_html]# ls index.html sun-j2ee-ri_1_3.dtd (WTF? What happened to all the single-appliation directories that are supposed to be there, including the one I've been working on for two weeks? It looks like 'cleanup' has destroyed all the deployed appliations, setting me back to where I was in early April when I first downloaded and installed J2EE, before I spent 4 hours deploying the first application and about 15-20 hours deploying the others.) Fortunately I had saved copies of all the jsp files in .../date/ that I had been working on, but still I'm really upset that I have to spend the next several hours in deploytool again and not know which if any of the deployed applications will actually work when I'm done. Now 16:56 as I launch deploytool ... 17:04 it's up and now I'm starting Netscape Navigator on the tutorial to see how to deploy one sample jsp and one sample hand-coded-java servlet ... first the sample jsp, but the only example they give instructions for is the horribly complicated Duke's Bookstore which I failed to deploy last week because the instructions didn't tell where to find the place in deploytool for a huge bunch of data. But wait, the section "what is a JSP" has instructions for the much simpler localized-date application, which wasn't too complicated, and which worked when I installed it before, so I'm going to install it again now. Starting at 17:12 ... at 17:25 I'm confused: I followed the instruction to create a new application called dateApp, but then when I looked in the file-tree view it showed not only the virgin dateApp that I had just created but also a DateApp still around from before, despite the fact that no such appliction really exists on the disk. So I'm going to assume that the DateApp is in the workspace for deploytool, able to survive shutting down deploytool and shutting down system several times and rebooting system several times, and I'm going to see if I can use that instead of a new application, short-cut the instructions a teeny bit... But first I need to find a way to delete the new application I created a few minutes ago ... OK, at 17:33 I've closed (without saving) that aborted attempt at a new dateApp application, and closed (from view of deploytool) the other applications I was working on weeks ago, and now I'm ready to shortcut the instructions for DateApp and see if it works. Meanwhile, I figure out a way to tell lower from upper case characters in that horrible font used by deploytool for all keyboard text: I sweep it with mouse then past into Emacs which uses a reasonable font where upper and lower case both look correct and distinguishable. Anyway, I clicked on the DateWAR, and waited many minutes for deploytool to show me any info, finally it came up but the JScrollPane for contents of WAR file was only two lines big and had arrows for scrolling adjacent with no gap, so I enlarged the window about a half inch vertically to allow room, but after several minutes wait deploytool finally did not what I wanted but a big mess, enlarging vertically much more than I wanted, but still fitting on the screen, but also enlarging horizontally, but shrinking the file-tree view so narrow the filenames are all off the edge invisible, so I expanded the window even more horizontally and am waiting for it to refresh as I type at 17:45, checking back now ... next I needed to drag the divider bar to make the section for file-tree view wide enough, but swing took several minutes to respond to any of my drag actions, finally got it done at 17:49. Verified the WAR name is correct and the two jsp files and two class files are in it, now 17:52. I hae a problem: The tutorial is for setting up a New component, where it takes me to the Wizard, where I just click Next for each stage in the configuring. But when there's already the component I want, in this case a WAR file, there are no instructions for going to the particular screen where I need to see if it's already done correctly and if not then fix it or do it for the first time. So at 17:56 I'm browsing likely tabs to see where the screens might be ... At 18:05 I give up, I can't find the screen that has the Web Component radio button and JSP filename combo box, so I'll just trust that it's correct already and if not correct this application won't work and I won't have any idea how to fix it. OK, context root looks OK, ready to deploy at 18:08 ... at 18:11 the screen came up for me to confirm which application to deploy, but the button to confirm was off the bottom of the visible screen, so I had to drag the window up, and I'm now waiting for swing to refresh the window so I can read some text in the middle that is trashed and see where the button is for confirming, now 18:13 ... it wasn't until 18:16 when it finally finished refreshing the window so I could see the Next> button, pressed it, finally got to Finish button and pressed it at 18:17, now waiting for application to be deployed ... at 18:22 it hasn't even begun to show the deployment progress window, waiting for that to appear ... still waiting at 18:26, and I'm getting seriously worried, it's been churning the disk like mad all this time yet hasn't even begun to deploy the application nine minutes after I pressed the final confirmation button to invoke deploying. What has it been doing all this time? At 18:33 the disk suddenly stopped churning, so I looked in .../public_html/ and I see the date folder has been re-created, with only the official files of that application, none of the files I had created myself during the past several weeks. So maybe it installed the application but swing screwed up and never showed me the progress window? So I tried to click on the directory-tree view to see what servers exist, but no matter where I click in the main deploytool window it just beeps at me, as if there were a modal dialog in effect and I can't click anywhere else in deploytool until I dismiss the modal dialog. But there's no modal dialog on-screen, nor in the minimized-window items in the bottom-bar. Maybe there *is* a modal dialog on-screen, but it hasn't been painted on-screen, so I have to click all sort of random places near the center of the screen until I chance upon the OK button in the dialog? Trying that now at 18:39 ... well I must have clicked well over a hundred different places in the general region where I remember the OK button was a week or two ago when I previously deployed an application, and I never could find it, so at 18:41 I gave up and clicked the X (close) box at the top of the main deploytool window to exit the entire appliation, and at least that worked so I didn't have right-click it which probably would have trashed things badly. So anyway, let me see if that time from 16:56 when I started deploytool until 18:41 when I killed it, a total of one hour 45 minutes, was of any value, clicked on browser link to run the official date application, still waiting for jsp to finish compiling at 18:48 ... finally at 18:49 it asked if I'd accept a cookie (for JSESS presumably) and up came screen and it works. Now let me copy the other jsp files from backup copies ... done at 18:55, now going to test a few of the JSPs that I had been working on ... yes, getstuff.jsp and ShowJspEnv.jsp both work. Now I can finally get back to where I was working on DataFlow.jsp and jump1.jsp->DataFlow.java/class way back around 16:18, over 2.5 hours ago. At 19:04 I've clicked on link to try DataFlow.jsp for the first time, waiting for jsp to compile, done. ... ... lots of steady work using my new linear-dataflow debugging method in the jsp but regular TDD (Test-Driven Development) in the java code being called, accomplished the following benchmarks: - Wrote program to check my interfaces and the classes that are supposed to implement them, both my own classes and system classes, and configured it for MinimalHttpServletRequest interface, and edited my classes and interfaces until everything passed. (After I have wrapRequest fully working I'll have to do the same interface-check for *Response and *Session.) - I needed to check for null pointer at the start of wrapRequest, as standard good programming practice, and I decided to make use of that to introduce another case, where there's no Request object at all, not even a fake one, so wrapRequest makes one. Got that working. - For case of existing system-supplied HttpRequest, got logic for diagnosing that case written and working I think, but I started getting bitten by the serve caching the old class file so it refused to ever load my last 3 sets of changes, so I decided to do a shutdown of J2EE and restart it. It had just started shutting down on May.21 about 2 AM when suddenly the machine froze, no disk activity, and mouse cursor wouldn't budge at all no matter how I jiggled trackball for several minutes. (I'm used to J2EE tying up the system so much that the disk is churning madly and the cursor is very erratic, but whenever the disk is quiet then the cursor starts working perfectly. But not this time. This was something bad that never happened to me on this laptop before, although I was use to occasional freezes of my Macintosh if I'd run buggy software.) So then I decided I needed to do an emergency shutdown, so I tried various things I remembered from the campus Windows system, and also tried to re-create a week or so ago when I accidently triggered an emergency shutdown. Finally I tried pulling the power switch that is used for starting the laptop, and voila, instant power-off. Then I pulled it again and the machine booted up, except because it hadn't been shut down properly it had to do a complete disk audit, found one bad inode it had to delete, nothing else bad, so it's back up for me to type into this log file. At 02:25 I'll start J2EE and see what happens ... OK, it's starting. ... Hey, at 02:33 it works: Here's what's on screen: * HSA returned WrappedHttpServletRequest@6e21f5 with mode=2 here's the relevant jsp scriptlet printing that: MyHttpServletRequest myReq = HSA.wrapRequest(reqO); if (myReq==null) { out.println("*** Null pointer came back ***" + br); } else { out.print("* HSA returned " + myReq + " with mode=" + myReq.getAttribute("org.maasinfo.mode")); } and here's the relevant code in HSA.java explaining what that value of 2 means: public static final int HTTP = 2; if (reqO instanceof javax.servlet.http.HttpServletRequest) { wReq.setAttribute("org.maasinfo.mode", new Integer(HTTP)); return wReq; } So the basic framework of my multi-UI adapter for Servlets is working so far as I've programmed for wrapRequest, and next (after a half night's sleep) I need to do the same for wrapResponse, and then copy all the linear code from the scriptlet in DataFlow.jsp to DataFlow.java and make sure it works there too, then try running DataFlow.java from a test rig that doesn't require J2EE and doesn't cache my class files, and then ...