Monday, December 08, 2003
My Blog has Moved...
My blog has moved over to WordPress
Saturday, August 02, 2003
More on Drive Cleanliness...
I blogged a couple of weeks back on setting up automated nightly defrags on WinXP.
The other day, as drive space was getting a little tight for my comfort, I ran the excellent utility JDiskReport from JGoodies to see just where all my drivespace was allocated and made an alarming discovery.
It seems that when I go through my normal work pattern of "start Jboss/Jetty, then hot-deploy, re-hot-deploy, re-hot-deploy (etc)...", it leaves behind expanded war-file directories in my c:\Documents and Settings\<username>\Local Settings\temp directory (NOTE: Local Settings is a hidden folder - so you have to have your view options set correctly to see it). The directories have the name pattern : Jetty_0_0_0_0_<PortNumber>__<WarName> (where <PortNumber> and <WarName> are your respective jetty listening port and war names).
I just got a new machine about a month and a half back, and in that time I had already accumulated about 1.2 GB worth of temporary files in such a manner (I go throught the, change/build/hot-deploy cycle many times a day).
Anyway - I decided to update my automated nightly defrag task to cleanup this stuff too. Here's the updated version - USE WITH CAUTION - the options I'm passing to DEL and RMDIR are equivalent to "do this recursively and don't prompt me whether I really want to delete all this stuff". The %TEMP% environment variable should expand to C:\Documents and Settings\<username>\Local Settings\temp directory by default. You might want to test this manually from the command prompt a few times just to make sure you've typed it in correctly :
::--- recursively remove all files in the temp directory, without :: prompting, then recursively remove all directories below the :: temp directory, without prompting del /F /S /Q "%TEMP%\*" > c:\temp\Defrag_CleanOutTemp.txt 2>&1 rmdir /S /Q "%TEMP%" >> c:\temp\Defrag_CleanOutTemp.txt 2>&1 ::--- defrag your local drives defrag /v /f c: > c:\temp\Defrag_C.txt 2>&1 defrag /v /f d: > c:\temp\Defrag_D.txt 2>&1
Saturday, July 05, 2003
Precompiling JSP's under JBoss/Jetty 3.2.1...
- Using Jasper (a JSP compiler), we'll transform the JSP's into .java files (servlets).
- Jasper will also spit out a web.xml fragment with servlet definitions and mappings for each of the above generated servlets.
- We'll use the ant jspc task to make the previous two bullets a little easier.
- We'll compile the .java files into .class files and then copy them into the WEB-INF/classes directory of the WAR
- We'll insert the web.xml fragment generated by Jasper into your normal web.xml file (at a very specific place).
- build your war as normal
<target name="dist" depends="compile"> <!-- copy required libs to WEB-INF/lib--> <copy todir="${dir.webinf}/lib"> <fileset dir="${dir.thirdpartytools.struts}/lib"/> <fileset dir="${dir.thirdpartytools.jstl}/lib"/> <fileset dir="${dir.search}/dist/lib" includes="${jar.name.search-domain}, ${jar.name.search-services}"/> </copy> <!-- copy classes we built earlier to WEB-INF/classes --> <copy todir="${dir.webinf}/classes"> <fileset dir="${classes}"/> </copy> <!-- copy the tld's we're using to WEB-INF/tld --> <copy todir="${dir.webinf}/tld"> <fileset dir="${dir.thirdpartytools.struts}/tld" includes="*.tld"/> <fileset dir="${dir.thirdpartytools.jstl}/tld" includes="*.tld"/> <fileset dir="${dir.config}/tld" includes="*.tld"/> </copy> <!-- these two properties are the generated web.xml fragment, and the resulting merged xml--> <property name="jspc.webxml.fragment" value="${dir.jspc.temp}/jspc-web-xml-fragment.xml"/> <property name="jspc.webxml.merged" value="${dir.jspc.temp}/merged-web.xml"/> <path id="jspc.classpath"> <path refid="cp.jspc"/> <path refid="cp.jboss"/> <path refid="cp.webclient-thirdparty.tools"/> <path refid="build.classpath"/> <fileset dir="${classes}"/> <fileset dir="${dir.webinf}/lib" includes="*.jar"/> </path> <!-- JSP -> .java --> <jspc srcdir="${dir.docroot}" destdir="${dir.jspc.gensrc}" verbose="9" classpathref="jspc.classpath" webinc="${jspc.webxml.fragment}"> <include name="**/*.jsp"/> </jspc> <!-- .java -> .class --> <javac deprecation="${deprecation.javac}" fork="${fork.javac}" source="${source}" debug="${debug}" srcdir="${dir.jspc.gensrc}" destdir="${dir.webinf}/classes" classpathref="jspc.classpath"/> <!-- merge the jspc generated web.xml fragment with the real web.xml--> <loadfile property="jspc.webxml.fragment.contents" srcFile="${jspc.webxml.fragment}"/> <copy file="${dir.webinf}/web.xml" tofile="${jspc.webxml.merged}"/> <replace file="${jspc.webxml.merged}"> <replacefilter token="<!-- @JSPC-INSERT-HERE@ -->" value="${jspc.webxml.fragment.contents}"/> </replace> <!-- Now war everything up --> <war destfile="${dist}/lib/${jar.name.epcportal-presentation}" webxml="${jspc.webxml.merged}"> <fileset dir="${dir.docroot}"/> <classes dir="${classes}"/> <classes dir="${dir.property.file}"> <include name="**/*.properties"/> </classes> </war> </target>
<property name="dir.jspc.temp" value="${dist}/tmp/jspc"/> <property name="dir.jspc.gensrc" value="${dir.jspc.temp}/gensrc"/>
<path id="cp.jspc"> <pathelement location="${jboss.home}/server/default/deploy/jbossweb-jetty.sar/jasper-compiler.jar"/> <pathelement location="${jboss.home}/server/default/deploy/jbossweb-jetty.sar/jasper-runtime.jar"/> <pathelement location="${ant_home}/lib/ant.jar"/> </path>
<!-- @JSPC-INSERT-HERE@ -->
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd'> <web-app> <!-- Struts Action Servlet Configuration --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> <param-value>ApplicationResources</param-value> </init-param> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>validate</param-name> <param-value>true</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- JSP-PRECOMPILER INSERTION POINT, DO NOT REMOVE, MODIFY OR MOVE THE FOLLOWING LINE--> <!-- @JSPC-INSERT-HERE@ --> <!-- Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- The Welcome File List --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/error404.jsp</location> </error-page> <error-page> <error-code>400</error-code> <location>/error400.jsp</location> </error-page> <error-page> <error-code>401</error-code> <location>/error401.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error500.jsp</location> </error-page> <!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/tld/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/tld/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/tld/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-nested</taglib-uri> <taglib-location>/WEB-INF/tld/struts-nested.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location> </taglib> <!-- JSTL --> <taglib> <taglib-uri>/tags/jstl-c</taglib-uri> <taglib-location>/WEB-INF/tld/c.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/jstl-c-rt</taglib-uri> <taglib-location>/WEB-INF/tld/c-rt.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/jstl-fmt</taglib-uri> <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/jstl-fmt-rt</taglib-uri> <taglib-location>/WEB-INF/tld/fmt-rt.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/jstl-x</taglib-uri> <taglib-location>/WEB-INF/tld/x.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/x-rt</taglib-uri> <taglib-location>/WEB-INF/tld/x-rt.tld</taglib-location> </taglib> <!-- Project Specific Tag Libs --> <taglib> <taglib-uri>/tags/epc</taglib-uri> <taglib-location>/WEB-INF/tld/epc.tld</taglib-location> </taglib> </web-app>
- The ant jspc task and jasper are VERY sensitive to the directory structure of your webapp. To get jasper to work, I had to make our pre-war directory structure pretty much exactly like the war archive structure. In other words, I had to make sure that the directory at task execution time was exactly like it would be in when looking at it in the war - all the classes that were destined to be in WEB-INF/classes were already there, all the libs which were destined to be in WEB-INF/lib were already there, all the TLD's were in their final destination (somewhere under WEB-INF), the web.xml file was already in WEB-INF, etc. This might seem obvious, but the ant <war> task will let you leave libs and classes in various directories and then bind them together into the appropriate archive with nested <lib> and <classes> tags
- Make sure you have at least Ant 1.5.3 (latest version of the ant jspc task)
Wednesday, June 25, 2003
Automated nightly defrags on Windows XP...
defrag /v /f c: > d:\temp\Defrag_C.txt defrag /v /f d: > d:\temp\Defrag_D.txt
Monday, June 23, 2003
CruiseControl version 2.2.1 is out...
http://sourceforge.net/project/shownotes.php?release_id=167306
We're using 2.0.2 on my current project and we love it. It takes a bit of maintenance and troubleshooting here and there (especially as the size of the project and number of tools grows), but it is definitely worth the investment to set your projects up in this.
Mozilla: Helpful Quick Reference Sidebars for Developers...
- HTML 4.01
- CSS 2
- Javascript (Reference and Guide)
- XSLT
Saturday, June 14, 2003
Experiences migrating from JBoss 3.0.4 -> JBoss 3.2.1...
<!-- HACK: This entry is only present to make IE treat the resulting HTTP response as a JNLP file instead of a JSP file. --> <servlet> <servlet-name>FakeJNLP-IE-Workaround</servlet-name> <description>our dynamically generated JNLP file (generated by this JSP)</description> <jsp-file>/FsxWebStart.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>FakeJNLP-IE-Workaround</servlet-name> <url-pattern>/FsxWebStart.jnlp</url-pattern> </servlet-mapping>
Sunday, June 01, 2003
Similarities between the Matrix Reloaded and the Wheel of Time (minor spoilers)
Saturday, May 31, 2003
Good tool for Debugging IE Dom...
Monday, May 19, 2003
Nice Little Article on Black Box Testing for WebApps with HttpUnit
Thursday, March 06, 2003
Maslow's Hierarchy of Needs: Food, Shelter, RAM...
- IDEA
- JBOSS/Jetty
- Oracle 9i
- Javac (when building/executing tests)
RAM = GOODOh well, at least my lack of RAM predicament gives me plenty of time to write blogs in notepad while I'm waiting around for a test to complete... Speaking of - I really like the XP Remote Desktop Connection facility (its built on top of Terminal Server). Its much more like setting your display in X-Windows than Microsoft's previous support (e.g. NetMeeting). One of the things I really love about my laptop is the crisp 1600x1200 display. With Remote Desktop Connection I can login to a server with a crappy video card and still run at 1600x1200 (way cool). I know you could do this a decade or more ago on Unix, but hey - at least MS is improving :)
Wednesday, March 05, 2003
Keep IDEA from Hanging for significant periods of time while doing GC...
lax.nl.java.option.additional=-XX:+UseConcMarkSweepGCThe full thread is here if anyone's interested :
http://www.intellij.net/tracker/idea/viewSCR?publicId=9910
Monday, March 03, 2003
Wish I had a JavaScript IDE...
Saturday, February 15, 2003
Nasty Webstart Classloader Bug Revisited...
public class UncaughtAwtExceptionHandler { public static void installAsUncaughtAwtExceptionHandler() { System.setProperty("sun.awt.exception.handler", UncaughtAwtExceptionHandler.class.getName() ); } public UncaughtAwtExceptionHandler() { } public void handle (Throwable ex) { // log the error... } }Now anytime an uncaught exception bubbles all the way to the top of the AWT-EventQueue thread, the handle method on UncaughtAwtExceptionHandler is called (and the AWT-EventQueue thread does not exit). The only constraints on one of these classes is that they must have a public, zero argument constructor and a method which matches the handle method signature (void return type, Throwable as the single parameter). I found this property by looking at the source for the AWT class EventDispatchThread (good thing they ship JDK's with the source). There is a comment on a private method which cautions that this property will one day go away when better API support for uncaught exceptions is provided (I believe this is scheduled for JDK 1.5). One other solution I explored while trying to solve this was defining a custom ThreadGroup in the main of the program, and creating a new main thread with the correct ClassLoader. Then I let the original webstart thread "end", while I started up our application in the newly created thread. You can override ThreadGroup's uncaughtException method to get a notification anytime a thread in that ThreadGroup dies (I was going to try to use this hook to send a runnable to the awt event queue via the SwingUtilities.invokeLater method that would reset the classloader in the new thread). Nonetheless, I could never quite get it to work the way I wanted (couldn't get the AWT-EventQueue to belong to my ThreadGroup in a Webstart application). I looked a thte source and it looks like the awt's dispatch thread uses the ThreadGroup and ClassLoader of the first thread that causes it to do anything (and I think WebStart was doing some awt stuff before our program even started). Anyway, it was around that time that I stumbled upon the property above, and I thought that would be a more foolproof solution (keep the event queue thread from dying in the first place). I really hope they fix this bug in the next version of WebStart (I'm suprised they haven't done it already).