<meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> <!-- data-ad-client=ca-pub-4320963827702032 --> <!-- --><style type="text/css">@import url(https://www.blogger.com/static/v1/v-css/navbar/3334278262-classic.css); div.b-mobile {display:none;} </style> </head><body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7256432\x26blogName\x3dThe+Frustrated+Programmer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttps://frustratedprogrammer.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://frustratedprogrammer.blogspot.com/\x26vt\x3d4213664491834773269', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
| Saturday, August 28, 2004

Last year you wrote some middleware using EJBs. This year your boss tells you that a C++ client needs to talk to those beans. You consider SOAP, but are dicouraged by reading about its performace. Papers showing SOAP is 100 to 1000 times slower than RMI are all over the place. Even with the newest pull parsers it still can't meet your performance needs of sub 200ms response times for up to 1000 transactions per second.

You start to look at other technologies, some more traditional, others a little newer.


CORBA

If your EJB container supports it, you can start using CORBA right away. But CORBA adds a lot more moving parts to the system. Your client code is more complicated. And its slower than some of the other solutions.

JNI Bridge


As strange as it might sound, there is actually a commercial product built around this. C++ wrappers are generated, which invoke RMI stubs via JNI. The client interface is simplier and faster, but you level of 'moving parts' is still fairly high. You need a JVM installed on each of your C++ clients.

Native C++ JNI


I couldn't find much information on this, but if your generating C++ wrappers, why not just generate an entire C++ RMI client. I found a small sample application / proof of concept.



So what do you do? Choose one of these? Maybe something more complicated with MQ to MDBs? Maybe a non-standard remoting method like Hessian?

| Tuesday, August 24, 2004

Kelly was a hard-core emacs user, while I used vi. We went our separate ways when Fusura.com imploded. In the last year I've fallen in love with IDEA, but the reasons I use it are common to most IDEs. Now that we are working at the same company again, I've tried to explain these reasons to Kelly with no results. This is an open letter to him in an attempt to explain why spending a few hours up front to configure an IDE will save days in the end...

Navigation

  • Fast opens - In IDEA I just use ^N to open any file in the project. No more cds, not more clicking through directory trees. I just start to type the file name and IDEA gives me the available matches across all the directories in the project.

  • Find usages - I used to have to generate JavaDoc or find+grep to find all the callers of a method or variable. This is a ton easier.

  • Goto declaration/implementation - Not completely unique to an IDE, since I can some of this with ctags, but its still a huge help.

Refactoring - There are plenty of refactorings available in IDEs, but these are the ones I commonly use.


  • Extract Method - Not only is IDEA really handy at breaking up complicated code, it also finds where I've cut and pasted this code and cleans those up too!

  • Rename - On my new project, I'm starting to attend code reviews. Its obvious people have never used an IDE with refactoring support. There were three differnent naming conventions used in one file. When its this easy to fix things, it makes it so painless.

  • Safe Delete - Not only does IDEA check is your file is used across Java code, but it also checks my struts-config.xml, web.xml and my JSPs.


Other

  • No compile errors - Sounds simple, but I went back to VI and saw a compile error for the first time in a year.

  • Code Generation

    • I write instance variables and generate getters, setters and constructors.

    • I write my struts action and while I'm doing it I call a method in my business logic that doesn't exist yet, passing it a constant from another file that doesn't exist yet, IDEA generates the stubs for these for me.

    • When I cut and paste code, IDEA automatically formats and adds missing imports for me.




These are my reasons, they're features I use on a daily basis. If you have more, please add a comment. If you've actually tried an IDE and are still using an editor, please leave a comment too.

| Thursday, August 19, 2004

I was reading about Null Pointer Exceptions today, and finally read up on Nice. They had this to say about NullPointer exceptions:

To prevent [a NullPointerException], a reference must be tested before use. However it is easy to forget to do so. Furthermore, there are references that are never null, or rather that should never be. Testing such references clutters the code.


Nice provides the following solution:
Here obviously comes our motto: all this checking should be done automatically. This is exactly what Nice does. One documents whether a type can hold the null value by simply prefixing it with the ? symbol. Thus: ?String name; is the declaration of String variable that might be null. To get its length, one must write int len = (name == null) ? 0 : name.length();. Calling name.length() directly is a type error. It would only be possible if name was defined as String name = "Some non-null string";


I agree with Nice's statement of the problem, but I'd like to present a different solution. If the problem is that people forget to write null checks, why not force it with the language? Something like this:
The following Java code:

public execute( Form form ) {
String type = form.getType();
if( type != null ) {
doSomething( type );
} else {
throw new Exception("type is required");
}
}

Could be replaced with:

public execute( Form form ) {
form.getType() : String type {
doSomething( type );
} null {
throw new Exception("type is required");
}
}

The idea is this: If form.getType() returned null, the block of code following the method invocation would not execute. Otherwise, 'type' is assigned the return value from form.getType() and its scope is only visible in that block of code. After thinking about it a little I came up with the following rules:

  • Assignment can only be used for new (object instantiation) or primitives.

  • A method call can be suffixed with : [type] [variable name] { [statements] } Statements will only be executed if the return value is not null.

  • null could also be used as a keyword following this block of statments, similar to 'finally'. Statements following null will only be executed is the return value is null. This block is optional, similar to 'finally'.

  • Method calls with assigments can be grouped together and the block of code following them will only be execute if all return values are not null.

  • for and while loops could be modified to use a similar syntax.

  • null can still be returned from methods or passed to parameters.



Its far from perfect. Specifically, I don't know how to handle class and instance variables or parameters. But I think it might have some promise.

| Friday, August 13, 2004

With 50% more votes than its nearest enhancement request, Bug #4977599 , "Provide documentation in Chinese" is the most requested out there. The author of the original request posted his thoughts on a chinese technical bulliten board. Sun's response to this request is:
Thanks for the comments and support. Currently, we only localize documents into Japanese due to business requirement. We will strongly consider localizing the doc into Chinese in the next release. thx!


I've looked through some of the Japanese documentation, and I'm not sure that its very useful. If Sun chose a standard like SVG things might be a little different, but things like this don't help anyone, do they? Besides images that are not localized, JavaDoc has no way to specify comments in other languages. All the method names are english words or phrases that can not be translated either. I'm not saying that its not a good idea to translate the documentation into Chinese. After all, they are a rising star in the world scene. I just question the usability of whats getting translated.


| Monday, August 09, 2004

I hit an interesting bug in java.util.GregorianCalendar today. I was writing some reporting code that needed to find the number of widgets sold for each week of the year. I found the current week of the year from Calendar using get(WEEK_OF_YEAR), then selected the sum of selected the sum of widgets sold where TO_DATE( sale_date, 'WW' ) = ?. The documentation for each week of year calculation is below:

WW
Week of year (1-53) where week 1 starts on the first
day of the year and continues to the seventh day of the year.


WEEK_OF_MONTH
Field number for get and set indicating the week number
within the current month. The first week of the month, as
defined by getFirstDayOfWeek() and
getMinimalDaysInFirstWeek(), has value 1. Subclasses
define the value of WEEK_OF_MONTH for days before the
first week of the month.


Specifically, Oracle thinks of dates as full seven day weeks. Oracle weeks always start on the same weekday as the first day of the year. In constrast, Java thinks of weeks as you traditionally see on a paper calendar. In the en_US locale, weeks always start on Sunday, except the first week of the year, which starts on 1/1 regardless.

In an attempt to have GregorianCalendar behave like Oracle, I tried Calendar.setMinimalDaysInFirstWeek(7). This didn't work as I expected. GregorianCalendar called still wanted the week change to take affect on Sundays, in addition, it reported the first 3 days of the year in 2004 as being in week 52.

My solution was to use my own computed value to match oracle's week calculation:

oracleWeek = (normal.get( Calendar.DAY_OF_YEAR ) - 1) / 7 + 1


Here is a code sample to show this:

public static final int ORACLE_WEEKS[] = { 52,1,1,1,1,1,1,1,2,2 };
public static void main( String args[] ) {
Calendar normal = new GregorianCalendar(); normal.set( Calendar.YEAR, 2004);
Calendar adjusted = new GregorianCalendar(); adjusted.set( Calendar.YEAR, 2004 );
adjusted.setMinimalDaysInFirstWeek( 7 );

for( int i = 1; i < 10; i++ ) {
normal.set( Calendar.DAY_OF_YEAR, i );
adjusted.set( Calendar.DAY_OF_YEAR, i );
System.out.println("1/" + i
+ " | " + ORACLE_WEEKS[i]
+ " | " + normal.get( Calendar.WEEK_OF_YEAR )
+ " | " + adjusted.get( Calendar.WEEK_OF_YEAR)
+ " | " + ((normal.get( Calendar.DAY_OF_YEAR ) - 1) / 7 + 1 ) );
}
}

It produces this output (headers added):

Day | Oracle Week | Calendar | adjusted | calculated
| WW | WEEK_OF_MONTH | |
1/1 | 1 | 1 | 52 | 1
1/2 | 1 | 1 | 52 | 1
1/3 | 1 | 1 | 52 | 1
1/4 | 1 | 2 | 1 | 1
1/5 | 1 | 2 | 1 | 1
1/6 | 1 | 2 | 1 | 1
1/7 | 1 | 2 | 1 | 1
1/8 | 2 | 2 | 1 | 2
1/9 | 2 | 2 | 1 | 2

I also tried to add adjusted.setFirstDayOfWeek(5). While this corrected the table for the year 2004, the 1/1/2003 was still in week 52.

A quick search of bugs produced a bunch related to WEEK_OF_YEAR, but all were either fixed or not a bug. This seems like a bug to me, maybe I'm still using things wrong. If things are working as designed, I suggest writing a wrapper around GregorianCalendar called OracleCalendar, which overrides get(int) set(int, int) and roll( int, int ).

| Saturday, August 07, 2004

Inversion of Control/Dependency Injection are still big buzz words. Popularity continues to grow for IoC "containers", notably:

In general these reduce couplings between components, letting the IoC container piece your objects together. Struts has some built-in functionality for supporting IoC on data sources, form beans and actions.

Data Sources
A data source can be configured in the struts-config.xml file and accessed through the base Action class's getDataSource() method. A concrete implementation of a datasource can be retrieved through a symbolic name. See Struts - Accessing a database for more information.
The scope of these objects is Global, only one is created per Application.
Every data source is allocated at application startup weather it is used or not.

Form Beans
Form Beans are either custom Java classes (with simple getters and setters for data properties) or generic objects (like Maps or Dyna*Beans). Generic objects can be configured with a list of properties and constraints with default values on those properties, but custom Java classes cannot be configured at all.
The scope of these objects is determined by the Action using the Form Bean. They can be easier Session or Request.
Form Beans are allocated as they are needed.

Actions
Actions map a symbolic name to a concrete class. This class is configured with a form bean, a set of mappings and a generic String parameter.
The scope of these objects is Global, only one is created per Application.
Actions are allocated as they are needed and cached until the next use.

Analysis
The actions are the work-horses in struts. They need to interact with business logic classes, they almost always get a user profile object out of the session. The tight coupling that currently exists in struts actions make them difficult to unit test and reconfigure.

Struts has a fair amount of logic hardcoded in ActionServlet and RequestUtils for performing this Inversion of Control. If this were abstracted out into a plugable helper class, the core struts code could decrease while allowing other projects to maintain the burden of this work.

A new interface called IoCAdaptor could be created, along with three implementations of this interface:

  • StrutsBuiltinIoCAdaptor
  • PicoIoCAdaptor
  • SpringIoCAdaptor


One of these adaptors could be installed into the servlet context by configuring a struts plug-in in the struts-config.xml.

Recently Spring added support for Struts integration. This support came in two forms:

  • Proxy delegates to Spring-managed Action
  • Action has easy access to a Spring context


While this is a nice advance over no integration, I'd still like to see work done at the core of Struts. This would improve the following issues:

  • The IoC code could evolve separately from the struts core.
  • IoC could be supported for Form and DataSources, not just Actions.
  • No need for a special proxy action -- Integration would be more natural.


[Note: This entry was originally written back in December 2003. Webwork and Spring among other UI frameworks fully support dependency injection.]

| Thursday, August 05, 2004

Dan Cederholm, web design guru, recently posted another quiz on his site. He was asking how to represent an address in HTML. The most popular was this:

<address>
ABC Widgets, Inc.<br />
100 - 1234 West Main Street<br />
Anytown, State<br />
Zip<br />
Ph: 555-555-1234<br />
Fax: 555-555-1234<br />
</address>


This is great if your looking for a compact solution to display a simple address. But its a classic case of WYSIAYG (What you see is all you get). If instead, the address was marked up in a standard manner, then search engines and other crawlers could mine this data. Just look at what google has done with the <ul> and <dl> elements. This kind of data mining wouldn't be possible without the proper structure.

Enter XHTML and custom schemas. If google and the other search engines were to define standard schemas (or just put their stamp of approval on the existing schemas) I believe sites would start to use them because of the improved search results they would receive.

Here is my solution with a custom schema:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns:html="http://www.w3.org/1999/xhtml" xmlns:postal="http://www.foo.bar/postal">

<html:head>
<style type="text/css">
postal\:address postal\:city {
display: inline;
}
postal\:address * {
display: block;
}
postal\:city:after { content: ", " }
postal\:phone:before { content: "Ph: " }

</style>
<html:title>Postal Address</html:title>
</html:head>
<html:body>
<postal:address>
<postal:name>ABC Widgets, Inc.</postal:name>
<postal:streetaddress>100 - 1234 West Main Street</postal:streetaddress>
<postal:city>Anytown</postal:city>
<postal:state>State</postal:state>
<postal:zip>Zip</postal:zip>
<postal:phone>555-555-1234</postal:phone>
</postal:address>
</html:body>
</html>


This example works fine in standards complaint browsers like mozilla, firefox and opera. If the search engines started to push the use of custom schemas, it might help nudge Microsoft into supporting the existing standards. Also note that the extra cruft like punctuation and labels for the address are added through CSS.

| Wednesday, August 04, 2004

I don't want this to turn into 'The Frustrated Blogger', but here are a list of the wish list items I've submitted to blogger. If you use blogger, please let them know you want these too.

  • Use an Open support system. Something like bugzilla, where I can see what is happening to my trouble tickets and enhancement requests. Bugzilla also supports voting, picking off new features to implement will require less 'gut feel'.
  • Add a button at the bottom of the Edit Post window to set the Time & Date to the current time and date.
  • Support trackback.
  • Add grammar checking.
  • Support exporting posts (in a real way).
  • Add a 'sub tab' under 'Posting' for 'Drafts' to show all Posts in draft mode.
  • Add RSS support.
If you do agree with these and have a Blogger.com account, please wite Blogger Support and tell them. If you have others, let me know. I'll write their support too.

| Tuesday, August 03, 2004

This posting is used to describe a bug in Blogger.com's preview mode to their customer support.

When publishing a Post in Blogger.com, the Post is converted into a single line in HTML. Whitespace doesn't matter in HTML, so its really not a big deal. Unless of course, you use the <pre> tag, like I do in this blog in almost every post. Fortunately, I also use 'Convert line breaks', which converts my line breaks in the Edit Post window into <br /> tags. So my posts end up getting published exactly as I entended.

The rendered HTML for my last Post looks like this:

<div class="post-body">

<p><a href="http://twasink.net/blog/archives/2004/08/tip_to_the_stru_1.html">This blog entry</a> talked about some great issues with session scoped struts forms. I found another one the hard way today:<br /><br />When I added some properties to my session scope form in struts today, I modified my action to pass those properties to the business logic, recompiled, redeployed. But I ended up with:<br /><pre><br />StandardWrapperValve[action]: Servlet.service() for servlet action threw exception<br />java.lang.NoSuchMethodException: Unknown property 'foo'<br /></pre><br />I checked and rechecked things, but I still got the same error.<br /><br />It turned out that because I was using a DynaBean for my ActionForm, combined with <a href="http://jakarta.apache.org/tomcat/tomcat-5.0-doc/config/manager.html#Restart%20Persistence">Tomcat 5's Restart Persistence</a>. The old configuration for my form was still cached in the session. The solution was either delete $CATALINA_HOME/work/Catalina to remove the cached session or just logoff and login again.<br /><br />Normally I love the fact that I don't need to re-login after restarting, but this was a pain. </p>


</div>


The bug is in the preview mode. Where for some reason, it doesn't render the posts all on one line, but it still implements the 'Convert line breaks' feature. This causes all text in a <pre> tag to be double spaced, plus other little odd formatting issues.

The HTML for my last Post IN PREVIEW MODE, looked like this:

<div class="post-body">

<p><a href="http://twasink.net/blog/archives/2004/08/tip_to_the_stru_1.html">This blog entry</a> talked about some great issues with session scoped struts forms. I found another one the hard way today:

<br />
<br />When I added some properties to my session scope form in struts today, I modified my action to pass those properties to the business logic, recompiled, redeployed. But I ended up with:
<br /><pre>
<br />StandardWrapperValve[action]: Servlet.service() for servlet action threw exception
<br />java.lang.NoSuchMethodException: Unknown property 'foo'
<br /></pre>
<br />I checked and rechecked things, but I still got the same error.
<br />
<br />It turned out that because I was using a DynaBean for my ActionForm, combined with <a href="http://jakarta.apache.org/tomcat/tomcat-5.0-doc/config/manager.html#Restart%20Persistence">Tomcat 5's Restart Persistence</a>. The old configuration for my form was still cached in the session. The solution was either delete $CATALINA_HOME/work/Catalina to remove the cached session or just logoff and login again.
<br />
<br />Normally I love the fact that I don't need to re-login after restarting, but this was a pain. </p>

</div>


See the difference?

Update: Within 12 hours I got this heart-felt response from the blogger support team. I will always remember the personalized service I've received from them.

Hi there,

Thanks for your suggestions regarding the new Blogger interface. We are very interested in feedback from our users so we know what works and what we should improve, so we will certainly take this issue into consideration.

Thanks for using Blogger!

Best regards,
Blogger Support

This blog entry talked about some great issues with session scoped struts forms. I found another one the hard way today:

When I added some properties to my session scope form in struts today, I modified my action to pass those properties to the business logic, recompiled, redeployed. But I ended up with:

StandardWrapperValve[action]: Servlet.service() for servlet action threw exception
java.lang.NoSuchMethodException: Unknown property 'foo'

I checked and rechecked things, but I still got the same error.

It turned out that because I was using a DynaBean for my ActionForm, combined with Tomcat 5's Restart Persistence. The old configuration for my form was still cached in the session. The solution was either delete $CATALINA_HOME/work/Catalina to remove the cached session or just logoff and login again.

Normally I love the fact that I don't need to re-login after restarting, but this was a pain.

| Sunday, August 01, 2004

I was profiling our application with optimizeIt looking for memory leaks when I noticed that the tag library DisplayTag was holding on to my lists of objects. I looked in the source and it was letting go of the list in the release() method, just like it should. I couldn't figure it out, so I called a friend who had done his homework and read the specs. He explained the behavior a lot better than the JavaDoc below:

public void release()
Called on a Tag handler to release state. The page
compiler guarantees that JSP page implementation objects
will invoke this method on all tag handlers, but there may
be multiple invocations on doStartTag and doEndTag in
between.

The spec added a little more, but its still a little vague:

Once all invocations on the tag handler are completed, the
release method is invoked on it. Once a release method is
invoked all properties, including parent and pageContext, are
assumed to have been reset to an unspecified value. The page
compiler guarantees that release() will be invoked on the
Tag handler before the handler is released to the GC.

Well, Billy explained that release() will not always be called immediately after doEndTag(). If the container wishes, it might want to wait until the next call to your tag. If this next call passes the exact same arguments, it will just invoke the tag again, without setting attributes on it. Under certain circumstances, like tag pooling, release will not be called until container shuts down.

As I was writing this entry, I looked about a bit. There is a lot of misleading information on this. Notice this article on ONJava.com:
The container also guarantees that release will be invoked on the tag handler before the end of the page.


According to the spec, this isn't true. release() will get called before the tag is GC'd, that has nothing to do with a page and its scope or rendering.

Update: Tag pooling can be turned off in Tomcat by adding the following to your CATALINA_HOME/conf/web.xml. Add this to the servlet/servlet-name='jsp' section.

<init-param>
<param-name>enablePooling</param-name>
<param-value>false</param-value>
</init-param>

One of the beautiful features of Hibernate is that you can finally work with objects in your persistence layer. Once your mappings are setup, you can keep playing with object oriented code. Why don't we have anything like this with UI frameworks?

Currently if I have the following classes in my object model. Cat is a nomal object/table, and gender is an enumeration/lookup table.

public class Cat {
private Integer id;
private String name;
private Integer age;
private Gender gender;
[...]
}
public class Gender {
private Interger id;
private String label;
}

And I have the form:

Cat Name: ___________
Cat Age: ___________
Cat Gener: [Male ]<-
[Female]

I'm always left hand-coding some genderId field in my form and manually looking up the gender based on this in my Action, when the form is submitted. The more relationships my objects have, the mroe repetitive code I have like this. In all the frameworks I've seen, including ones that let you use your business obejcts directly (like Spring and WebWork), I can't see how I can automatically build these relationships between objects. I think the UI framework should handle all this for me. I don't even mind if they have to look in my hibernate config files.

The closest thing I've seen is the Converters in Webwork, but they are not well documented. I think OGNL might be up to the task, but I'd have to write custom converters for each type in my object model. Thats a little too much.