Monday, August 25, 2003

Struts JSTL EL Validator rule

I told Erik about my new Validator rule, and he told me to try to contribute it. Erik is my open source mentor.

I tried to contribute it. I subscribed to the struts dev list, and posted the following:


I am new to this list so I apologize if I break any etiquette. I was thinking that I don't like validatewhen or requiredif so I wrote my own that uses JSTL EL. (I like the idea behind requiredif and validatewhen just not the implementation.) I believe this approach has several advantages over requiredif and validatewhen. I call this new rule validateel (I have not thought of a better name for it yet...).


Why write your own expression language? Why not use OGNL or JSTL EL? I think JSTL makes the most sense for the followig reasons:

1) EASY TO LEARN
The first advantage of this approach is it is easy to learn since developers know JSTL EL already. JSTL EL is easy to learn and you have to learn it for JSP 2.0 anyway. In fact, developers should be using JSTL tags in place of logic:* tags already.

2) ACCESS TO PAGE CONTEXT
The nice thing about this rule is that it has access to the complete pageContext (Headers, Request Parameters, Session, the whole thing) name space like any JSTL tag. (more on this trick later).

Since I am using JSTL EL I can make my expression as complex as need be, e.g., I can check to see if one date is before another or if a string starts with a certain substring. It is completely powerful, and yet very easy to learn and use.

3) VERY LITTLE CODE
This rule was very easy to implement. It relies on the Jakarta JSTL EL implementation. I don't see the point in adding a new expression language just for Struts when Struts relies on JSP and Servlets and JSP will be using JSTL. (Less code to add means less code to maintain....)

DETAILS:
...
(the rest you have seen in my blog)


This message was far more democratic and polite than my blog entry.

Thursday, August 21, 2003

What is requiredif and validatewhen.....??? (Struts validator)

I wrote about the JSTL validator that I created that I though was better than requiredif and validatewhen, and someone wrote me an email asking what requiredif and validatewhen were. (see my blog entry about the JSTL validator too)

They (requiredif and validatewhen) both account for...making fields required based on the value of other fields, or checking a relationship between fields.

So here goes....


Let's assume you want to make the state fields (as in a US state like a province in other countries) conditionally required only if the US checkbox field is set or the country drop down field is equal to the country code “us”. You would use the requiredif rule. The entry in your validation.xml file would look like this:


<form name="inputForm">

<field
property="state" depends="requiredif">
<arg0 key="inputForm.state "/>
<var>
<var-name>field[0]</var-name>
<var-value>us</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>fieldValue[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>field[1]</var-name>
<var-value>country</var-value>
</var>
<var>
<var-name>fieldTest[1]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>fieldValue[1]</var-name>
<var-value>us</var-value>
</var>
<var>
<var-name>fieldJoin</var-name>
<var-value>OR</var-value>
</var>
</field>


The field[n], fieldTest[n] and fieldValue[n] variables setup the expression. Thus the above states that in order for state to be required the us field has to equal “true” or country has to equal “us”. The fieldJoin variables joins the two expression. The fieldJoin value can be OR or AND, if AND then both of the expression have to be true. In addition to using EQUAL as a fieldTest, you can also use NULL and NOTNULL to see if the related properties are NULL or not.
The above is nice because it negates the need to override the ValidateForm’s validate method. However, it would not work for our password example earlier. For that more would be needed.
Requiredif might be deprecated in future releases
Future version of Struts passed version 1.1 may deprecate requiredif. The requiredif is considered very complex, especially when dealing with indexed fields (arrays of beans). The recommended way to perform this type of validation will be with the validwhen rule.

Beyond 1.1 conditional validation
As we showed earlier it is often the case that fields are validated based on the value of other fields. The example we did earlier in the chapter regarding password fields that are only valid if they are equal to each other. Thus we need to do more complex expressions than the requiredif rule provides. The validwhen validation rule is designed to handle these types of validation but it is not available until the release beyond 1.1. If you want in now, you will have to download the nightly source.
The validwhen rule takes a single test variable. The value of test must be a boolean expression. You can also refer to the current field under test with the keyword *this*. An example of using this with our password example is as follows:


<field property="password" depends="validwhen">
<arg0 key="inputForm.password"/>
<var>
<var-name>test</var-name>
<var-value>
((passwordCheck != null) and (*this* == passwordCheck))
</var-value>
</var>
</field>


The above would perform the same type of validation as the example we had earlier which required us to use override the validate method of the ValidateForm.
Here's a an example that redoes the requiredif example with validwhen as follows:



<field property="state" depends="validwhen">
<arg0 key="inputForm.state"/>
<var>
<var-name>test</var-name>
<var-value>
((us == "true") or (country == "us"))
</var-value>
</var>
</field>


You can also use validwhen with indexedProperties. Let’s say that the user registration form had two address, home address and shipping address. You would only want to validate the zip if address line one was set, you would use the following entry in the validation.xml file.


<field property="zip" indexedListProperty="addresses" depends="validwhen">
<arg0 key="inputForm.zip"/>
<var>
<var-name>test</var-name>
<var-value>((addresses [].addressLine1 == null) or (*this* != null))</var-value>
</var>
</field>

The address[] corresponds to the array of JavaBeans (e.g., ch15.Address). You are stating that the addresses[].zip is only required if the addresses[].addressLine1 is set.

Validator Rule that uses JSTL EL to validate multiple fields (and I hate coneys)

I was sitting at lunch eating a coney at Skyline in Cincinnati (not my favorite YUCK).... I from Tucson AZ, and I can't understand how Skylines draws such a crowd.

I was thinking how much I hate requiredif validator. I was also thinking that I don't like validatewhen much better.

Why write your own expression language? Why not use Ognl or JSTL?

I wrote my own version of validatewhen, and it uses JSTL lib from the Jakarta tag project. It took me about 20 minutes to write this. Short, sweet, and I'll never use validatewhen or requiredif again!

In my opinion, this new validate rule is much better than requiredif or validatewhen (at least the versions that I messed with). I can't believe someone did not think of tihs sooner.

It is also really easy to learn since you should know JSTL already.... Nothing special past that! (JSTL is easy and you have to learn it for JSP 2.0. You should be using JSTL tags in place of logic:* tags already.).

I call this new rule validateel (i have not thought of a better name for it yet... but I will, let me know if you think of one).

The nice thing about this rule is that it has access to the complete pageContext name space like any JSTL tag.
(more on this trick later).

Here is an example of using this rule to check to see if a passwordCheck field is equal to a password field as follows:


<field property="passwordCheck"
depends="validateel">
<arg0 key="inputForm.passwordCheck"/>
<var>
<var-name>test</var-name>
<var-value>
${value==form.password}
</var-value>
</var>



I created a FakePageContext class that takes a HttpServletRequest, and mocks up page context. I then add form to the fake page context as well as value inside of my new rule as follows:


PageContext pageContext = new FakePageContext(request);
String test = field.getVarValue("test"); //Get the test var (this is the JSTL expression)
pageContext.setAttribute("form",bean); //Map in the form
pageContext.setAttribute("field",field); //Map the field object (Just in case)
String value = ValidatorUtil.getValueAsString(bean, field.getProperty()); //Get the value of the property
pageContext.setAttribute("value",value); //Map the value into the page context.


The workhorse that actually does the JSTL expresion evaluation is from the JSTL lib. I just invoke it as follows:


result = (Boolean) ExpressionEvaluatorManager.evaluate("validateEL", test, Boolean.class, pageContext);



This was so easy... and IMHO it is better than requiredif and validatewhen. First... it uses JSTL which is an expression language people either know or should know (as it is required knowledge in JSP 2.0).

Here is the complete ValidateEL method and imports that implements this new validator rule.


import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;

import org.apache.commons.validator.Field;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorUtil;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.validator.Resources;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;

/**
* @author rhightower
*
*/
public class CustomValidatorRules {

public static boolean validateEL(
Object bean,
ValidatorAction va,
Field field,
ActionErrors errors,
HttpServletRequest request) {

PageContext pageContext = new FakePageContext(request);
String test = field.getVarValue("test");
pageContext.setAttribute("form",bean);
pageContext.setAttribute("field",field);
String value = ValidatorUtil.getValueAsString(bean, field.getProperty());
pageContext.setAttribute("value",value);
Boolean result = Boolean.FALSE;
try{

result = (Boolean) ExpressionEvaluatorManager
.evaluate("validateEL",
test,
Boolean.class,
pageContext);

}catch (JspException je){
// TODO fix
je.printStackTrace();
}
boolean r = result.booleanValue();
if (r == false){
errors.add(
field.getKey(),
Resources.getActionError(request, va, field));

}

return r;

}
....


Here is the listing for the FakePageContext (it fakes the needed parts of the context and leaves the rest noops):



import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;

/**
* @author rhightower
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class FakePageContext extends PageContext {
HttpServletRequest request;
Hashtable map = new Hashtable();

public FakePageContext(HttpServletRequest request){
this.request = request;

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getAttribute(java.lang.String)
*/
public Object getAttribute(String key) {
return map.get(key);
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String key, Object value) {
map.put(key, value);

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#removeAttribute(java.lang.String)
*/
public void removeAttribute(String key) {
map.remove(key);

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getOut()
*/
public JspWriter getOut() {
return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getSession()
*/
public HttpSession getSession() {

return request.getSession(true);
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getPage()
*/
public Object getPage() {

return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getRequest()
*/
public ServletRequest getRequest() {

return this.request;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getResponse()
*/
public ServletResponse getResponse() {
// no op
return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getException()
*/
public Exception getException() {
// no op
return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getServletConfig()
*/
public ServletConfig getServletConfig() {

return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getServletContext()
*/
public ServletContext getServletContext() {

return null;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#forward(java.lang.String)
*/
public void forward(String arg0) throws ServletException, IOException {
//no op

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#include(java.lang.String)
*/
public void include(String arg0) throws ServletException, IOException {
//no op

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#initialize(javax.servlet.Servlet, javax.servlet.ServletRequest, javax.servlet.ServletResponse, java.lang.String, boolean, int, boolean)
*/
public void initialize(
Servlet arg0,
ServletRequest arg1,
ServletResponse arg2,
String arg3,
boolean arg4,
int arg5,
boolean arg6)
throws IOException, IllegalStateException, IllegalArgumentException {
//no op

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#setAttribute(java.lang.String, java.lang.Object, int)
*/
public void setAttribute(String key, Object value, int scope) {
if (scope ==PageContext.PAGE_SCOPE){
map.put(key, value);
}else if (scope == PageContext.REQUEST_SCOPE){
request.setAttribute(key,value);
}else if (scope==PageContext.SESSION_SCOPE){
request.getSession().setAttribute(key,value);
}else if (scope==PageContext.APPLICATION_SCOPE){
//TODO fix
}
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getAttribute(java.lang.String, int)
*/
public Object getAttribute(String key, int scope) {
if (scope ==PageContext.PAGE_SCOPE){
return map.get(key);
}else if (scope == PageContext.REQUEST_SCOPE){
return request.getAttribute(key);
}else if (scope==PageContext.SESSION_SCOPE){
return request.getSession().getAttribute(key);
}else if (scope==PageContext.APPLICATION_SCOPE){
return null; //TODO fix
}else {
return null;
}
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#removeAttribute(java.lang.String, int)
*/
public void removeAttribute(String key, int scope) {
if (scope ==PageContext.PAGE_SCOPE){
map.remove(key);
}else if (scope == PageContext.REQUEST_SCOPE){
request.removeAttribute(key);
}else if (scope==PageContext.SESSION_SCOPE){
request.getSession().removeAttribute(key);
}else if (scope==PageContext.APPLICATION_SCOPE){
//TODO fix
}else {
// no op
}

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getAttributeNamesInScope(int)
*/
public Enumeration getAttributeNamesInScope(int scope) {
if (scope ==PageContext.PAGE_SCOPE){
return map.keys();
}else if (scope == PageContext.REQUEST_SCOPE){
return request.getAttributeNames();
}else if (scope==PageContext.SESSION_SCOPE){
return request.getSession().getAttributeNames();
}else if (scope==PageContext.APPLICATION_SCOPE){
return null; //TODO fix
}else {
return null;
}

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#getAttributesScope(java.lang.String)
*/
public int getAttributesScope(String arg0) {
// No op
return 0;
}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#findAttribute(java.lang.String)
*/
public Object findAttribute(String key) {
Object value = map.get(key);
if (value == null){
value = request.getAttribute(key);
}
if (value == null){
value = request.getSession().getAttribute(key);
}
if (value == null){
//TODO look it up in app scope
}
return value;

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#handlePageException(java.lang.Exception)
*/
public void handlePageException(Exception arg0)
throws ServletException, IOException {
// No op

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#handlePageException(java.lang.Throwable)
*/
public void handlePageException(Throwable arg0)
throws ServletException, IOException {
// No op

}

/* (non-Javadoc)
* @see javax.servlet.jsp.PageContext#release()
*/
public void release() {
// No op

}

}


For completeness...

I had to add this entry in validation-rules.xml


<validator name="validateel"
classname="ch15.CustomValidatorRules"
method="validateEL"
methodParams="java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,
org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
msg="errors.validateEL">
</validator>



It took me longer to write this blog entry then it did to write the above code. IMO if you are using requiredif or validatewhen, then you are wasting your time. Also, if you use the validator framework and you ever need to do a simple comparison of two fields... this is the way to go. With JSTL you have access to headers, attributes in session, request attributes, request parameters, and so much more.... Use this... it works and it is cool.

Here is how I would do the above in my own validate method of an ActionForm (for reference).


public class InputFormAll extends ValidatorForm {
...
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = super.validate(mapping, request);


if (!(password.equals(passwordCheck))){
errors.add(
"password",
new ActionError("errors.password.nomatch"));
}
return errors;
}



Using validateel is so much more terse! ${value==form.password} and I am done!

Tuesday, August 19, 2003

Proud Mary's.... I love it.... WIFI and Burgers!

dining011002

I am in Cincinnati and my hotel does not have high speed access. I was working in my hotel room with a dial-up modem.... Yuck!

I saw this place last night, and thought I would give it try.

Proud Mary's Burgers..... (near the down town library).

Turns out Proud Mary's has Hi Speed Access (WIFI baby), and yes I did bring my laptop (eventhough I did not know about the WIFI).

I have not tried the food yet (still waiting), but WIFI access is great!

Should frameworks fail when you do something stupid? I think so... fail fast and early (preconditions rule!)

What I don't like about GridBagConstraints....

Let's say I have a the following code that adds a checkbox, label and text field to a container.
The code is setup to allow the text field to stretch horizontally as follows:


JFrame frame = new JFrame(); //Create the frame.
JPanel content = new JPanel(); //Create the panel to hold the label and text field
frame.getContentPane().add(content); //Add the panel to the frame
content.setLayout(new GridBagLayout()); //Set the panel layout to GridBagLayout

JLabel label = new JLabel("Enter Name:"); //Create a label
JTextField field = new JTextField(10); //Create a text field
JCheckBox checkbox = new JCheckBox(); //Create checkbox

GridBagConstraints constraints = new GridBagConstraints(); //Create a constraint
//Add the label with the defaults
content.add(checkbox); //Add the label using defaults, OPPS!
constraints.gridx=1;
content.add(label); //Add the label using defaults, OPPS!

//Add the field to show to the right of the label,
//and take up the rest of the leftover space.
constraints.gridx=2;
constraints.fill=GridBagConstraints.HORIZONTAL; //Stretch horizontally
constraints.weightx=1.0; //Take up the rest 1 of 1
content.add(field); //OPPS!
frame.pack();
frame.setVisible(true);


Do you see what is wrong....

I forgot to use the constraint when I call add.
What happens? A nasty exception telling me that I dumb and forgot the constraint? Nope. I wish.
It happily add the fields with the defaults, which kind of behaves like FlowLayout.
I'd prefer if the framework would fail quickly, and let me know I screwed up.
The add method should throw some kind of precondition assertion. "Hey dummy you forgot to use a constraint" Exception. Instead of making me stare at the code. What if I forget? Let me know. This makes the framework easier to use.

The following code is correct....

JFrame frame = new JFrame(); //Create the frame.
JPanel content = new JPanel(); //Create the panel to hold the label and text field
frame.getContentPane().add(content); //Add the panel to the frame
content.setLayout(new GridBagLayout()); //Set the panel layout to GridBagLayout

JLabel label = new JLabel("Enter Name:"); //Create a label
JTextField field = new JTextField(10); //Create a text field
JCheckBox checkbox = new JCheckBox(); //Create checkbox

GridBagConstraints constraints = new GridBagConstraints(); //Create a constraint
//Add the label with the defaults
content.add(checkbox, constraints); //Add the label using defaults
constraints.gridx=1;
content.add(label, constraints); //Add the label using defaults

//Add the field to show to the right of the label,
//and take up the rest of the leftover space.
constraints.gridx=2;
constraints.fill=GridBagConstraints.HORIZONTAL; //Stretch horizontally
constraints.weightx=1.0; //Take up the rest 1 of 1
content.add(field, constraints);
frame.pack();
frame.setVisible(true);

Saturday, August 16, 2003

Interesting problem.... JSP 1.2... who is right?

I ran into a werid problem. I wrote a JSP/Struts application and deployed it to Resin 2.1. But....
When I deployed it to WebLogic 8.1 it stopped working.

It seems that Resin allows you to use the import directive (<%@page import="foo.Boo") to import classes that get used by useBean (jsp:useBean class="Boo"), but Weblogic does not allow this, you have to always use the fully qualified classname with useBean even if you imported it (jsp:useBean class="foo.Boo"). I wonder who is right. Resin feels right.

I guess I should not be lazy and go look it up in the spec. and then report the bug to whoever is doing it wrong. Anyone know off the top of their head????????

Extreme programming: Process vs. culture

Erik Hatcher and I use to work with Ryan Ripley at eBlox/PromoFuel. I need to read his article....

Extreme programming: Process vs. culture

Journal of Computing and Information Technology

I just recieved a copy of the Journal of Computing and Information Technology from the University Computing Centre in Zagreb, Croatia. They reviewed the book that me and Nick wrote (Java Tools for Extreme Programming). It was a nice review. And, they were kind enough to send us several copies along with the Journal that has the review in it.

The review was written by Hrvoje Bogunovic. I found his homepage, but alas there is not much there yet.

When I was up late working on the book at the coffee shop, I never dreamed someone in Croatia would write a review for it. We live in a small world. :)

--Rick Hightower

Friday, August 15, 2003

Fire Drill, Struts Best Practices

Started this week in total fire drill mode. Somehow it has managed to be a good week. I've spent a lot of time tihs week with WebLogic 8.1.

I finished my contribution to the second edtion of Mastering Struts by James Goodwill and Rick Hightower, which is now going to be printed under Wrox Professional Struts.

The last chapter I wrote was on Struts Best Practices, it covered the full gamut of things you need to do to use Struts on projects including StrutsTestCase, XDoclet for generation of validation.xml, transaction tokens to make sure a form only gets submitted once, when to use JSTL, how to write JSTL enabled tags, when to use Tiles, etc.

Wednesday, August 13, 2003

Books on Jakarta.... Crowbar Tech: Axis Book Dodgy

I saw this and I could not help linking to it. Thanks by the way... you made my day.
Crowbar Tech: Axis Book Dodgy


"
There are many good books on Apache's java software. At Crowbar, some of out favorites are:






Programming Jakarta Struts by by Chuck Cavaness


Java Development With Ant by Erik Hatcher, Steve Loughran


Apache Jakarta-Tomcat by by James Goodwill



And the best one, in our opinion is Java Tools for Extreme Programming: Mastering Open Source Tools Including Ant, JUnit, and Cactus by Richard Hightower, Nicholas Lesiecki.


Apache and Jakarta software is some of the best software available, commecial or not, according to our expert Crowbar analysts. The books on the subject should be of equally high quality. As for Wrox, here is a tip on how to create indexes.


"

Saturday, August 09, 2003

Contemplation

I just realized I worked 20 of the last 24 hours. This week I put in something like 75 hours. More like a 100 if you count travel time (planes).

Some of this time was spent on the book, most of it was spent at work, and a little was spent working on an article.

I've got some good feedback from the Tiles chapter I wrote as follows:

Craig Pfeifer writes:


Rick --

I read your chapter on tilles and I enjoyed it. We're using tiles right
now on my project, and when we did our initial investigation/prototyping we
went through the exact same steps that your chapter takes the reader through,
so I think the flow and approach are dead on. (Wow... that is cool! Thanks)

Here are my comments (nits at best):

- in your code samples, you use the struts tag libraries where JSTL tag
libraries exist (logic, bean). Is there any reason to use the Struts
tags over JSTL in these samples? Also, you use scriplets in a couple of
places,

(Are you sure? I am quite sure that I never use scriplets. I do use expressions a few times.

Since you can write a Tile layout as a type of Visual component, it is probably okay to use scriplets in some instances. Even the Tiles examples do this.

You can use Tiles as a replacement for some custom tags. The examples that ship with Tiles use scriplets quite a bit. Think about Tile Layouts as another way to write a Custom Tags like thing.

Tile Layouts have a lot in common with the JSP 2.0 tag file. The same rules do not apply to Tile Layouts IMHO that apply to JSP files. You should be judicious not dogmatic.

It comes down to intent. If you intend on creating a site layout then you should not use scriptlets ever. If you are creating a reusable visual component than sciplets are okay.

Again, I don't use scriplets in the examples. At least I don't remember doing so.....
)

I'm a firm believer that scriplets are evil (mostly), is there a reason
that JSTL wouldn't work?



(In the examples you cite there is not reason JSTL would not work. I just did not want to make the asumption that they were using/knew JSTL. I think they should use JSTL whenever possible over using the equiv. Struts tags. We cover JSTL in another section of the book and we suggest using JSTL as you state. If I were writing this book in a year or two, when everybody uses JSTL than that would be a different story... I would not use bean:write, logic:iterate at all.... I think.)


- Since Tiles is just a tag library, I'm guessing that using JSPC in
your ant build to precompile your pages works the same as without Tiles.
Again, my current project makes heavy use of tiles and we find that the first
hit to each page is fairly hefty. Once the page is compiled it's not a big
deal, but that first step is a doozy. IMHO using JSPC is even more important
w/Tiles than without.



(I agree, but don't want to cover this in this chapter.)



- I think the sample JSPs would be more effective w/o the layout markup
(table formatting, fonts, styles). When I'm reading this chapter I don't
care about the HTML parts of the page. Keep all this stuff in the sample
code that you package and make available for download, but it just
clutters the page in the text.



(Hmmmm.... I see your point. I like the context though.)



- In the "Understanding and using Tile Scope" section there's a sentance
"The tiles scope is a similar scope to the page scope." This section
needs to be reworked for clarity and so you don't use the word 'scope' (even
though it is the proper term) 3 times in the same sentance. I think a
picture would go a long way in showing this.



(I have a really good editor. He will fix that. I'll send him your comment as well just to make sure.)



All in all I think it's a very solid chapter! There were some
grammatical issues here and there, and the look and feel of the headings doesn't do
much for me, but I was reading more for content and organization.



(My grammar sucks! I can write grammaticaly correct if I need to, but I cannot engage the right and left sides of my brain at the same time when I am writing a technical book, i.e., the creative part engages when I write. I can correct other people's grammar but have a hard time correcting my own, because I know what I meant. Thank God for Editors like Tim Ryan. Sometimes I will let a chapter sit for a month and then copy edit it. It makes more sense to me then. For now, I am relying on Tim Ryan.

The look and feel of the book will change quite a bit. It goes through a bunch of stuff. You are seeing it in its raw form.)


Craig




Friday, August 01, 2003

Tutorial offers fast track to component integration- ADTmag.com

I am quoted in ADT Programmer's Report Weekly wrt to XDoclet (Tutorial offers fast track to component integration- ADTmag.com). Here is a small snip:

"XDoclet allows you to tack on meta data to language features like classes, methods and fields using what looks like JavaDoc tags. It then uses that extra meta data to generate related files like deployment descriptors and source code," said Rick Hightower, director of development at eBlox and author of the developerWorks Web site's "Enhance J2EE component reuse with XDoclets" tutorial.

This, said Hightower, can cut out quite a bit of redundant coding.

Read more at: Tutorial offers fast track to component integration- ADTmag.com. Bummer that they got my company name wrong.
I work at Trivera Technologies. I am the CTO of Trivera Technologies not the Director of Development at eBlox (I used to be).

I was in Ohio for the last two days. The weather was really nice, and I had a good time.



Tutorial offers fast track to component integration- ADTmag.com

I am quoted in ADT Programmer's Report Weekly wrt to XDoclet (Tutorial offers fast track to component integration- ADTmag.com). Here is a small snip:

"XDoclet allows you to tack on meta data to language features like classes, methods and fields using what looks like JavaDoc tags. It then uses that extra meta data to generate related files like deployment descriptors and source code," said Rick Hightower, director of development at eBlox and author of the developerWorks Web site's "Enhance J2EE component reuse with XDoclets" tutorial.

This, said Hightower, can cut out quite a bit of redundant coding.

Read more at: Tutorial offers fast track to component integration- ADTmag.com. Bummer that they got my company name wrong.
I work at Trivera Technologies. I am the CTO of Trivera Technologies not the Director of Development at eBlox (I used to be).

I was in Ohio for the last two days. The weather was really nice, and I had a good time.



Monday, July 28, 2003

Late night... procrastination woes

finally someone agrees with me...late night. It was bound to happen sooner or later.

Perhaps the root of the problem is a bad case of procrastination
. Anyway thanks for the good, timely advice. I've been at the coffee shop 5 times in the last week for my late night work sessions.

Friday, July 25, 2003

Erik Hatcher and Andy Barton are awesome.

Erik Hatcher is awesome. He just reviewed a chapter I wrote on the Tiles Framework. I swear Erik is the busiest guy in software development, yet always seems to take time to help others.

It was a long chapter, about 40 pages, and he had comments all the way to the end of the chapter. He really took the time to review it.


Andy Barton just reviewed my Tiles chapter too. You Rock Andy! Thanks!

Tuesday, July 22, 2003

Driven by Demons

I just read this quote from Erik's blog.

From http://www.washingtonpost.com/wp-dyn/articles/A28471-2003Jun24.html:

"All writers are vain, selfish and lazy, and at the very bottom of their motives there lies a mystery," he wrote in 1947. "Writing a book is a horrible, exhausting struggle, like a long bout of some painful illness. One would never undertake such a thing if one were not driven on by some demon whom one can neither resist nor understand."

Wow... I could not agree more. (Except the lazy part....)
Most great authors were drunkards or druggies. I either have to quit writing or don an addiction. I guess I never be great.

Writing is a mental mind screw for sure. It is addictive and painful. Every time I write, I always wonder, will this be read, will this be liked, will it be helpful.... my usual self confidense gives way to doubt and fear of critisism.

July 23rd
11:35 PM

It's my third night at the coffee shop. I've reached a new level of sleep deprived creativity. Did I mention that I am tired? I am considering going home to sleep. I got the monkey off my back by finishing the thing I needed to finish last night. Now I need to work on the next thing.


2:00 AM

I am out of here. Can't focus. Can't continue. Caffiene not working....

Catching up after my "praternity leave"

11:36 AM

I am at the all night coffee shop again (it has been a month or so since I've been here). I seem to get the most work done from 9 PM to 3 AM. No one to bother me. No phone. No radio. No TV. No kids. No spouse. No email. No connection at the coffee shop means I wont cruise the Internet, read other people's blog, read technical articles, read email, read news groups, read postings, etc. and mistake it for getting something done. How do you keep up with it all?


Plenty of caffiene and my laptop means I will get a lot of work done tonight and this morning. I've already got a lot done. I can't wait to finish this project.

I wonder how much productivety is lost due to the Internet. I realize it increases the flow of information, but sometimes it seems like an overflow of information. I love and hate it at the same time. It is useful and a big distraction. God's gift and Satan's curse.

Blogs are funny, any tin horn technical dicator can pontifcate an opinion no matter how bad or how stupid (myself included of course). I love and hate blogs. I read some blogs this afternoon. I wish all blogs had a reply button. Given my tendency for distraction maybe its better that they don't. Technical pontification is the scurge of all that is good about blogs. On the other hand, I value blogs ability to give context to technology by getting people's opinions about various technolgies.

I now have an office in my garage. It has four walls and an air conditioner. (Air conditioner is a must in Arizona not a luxury.) All I need now is a espresso machine, small fridge (for milk), and a timer to turn off the Internet from 9 PM to 3 AM, and I will never go to the cofffee shop again.


Here I am writing my blog in notepad, because I am not connected. Apparently, if you try hard enough distractions can be found without the Internet. Excuse me while I go read the newspaper. LOL

I'll wrap this blog entry up at the end of the night.

.....

3:15 AM
The crowded coffee shop, now has just two customers left. The card players, socialites, college students have all came and gone. I didn't get as far as I wanted to (about 1/2 as far to be exact), but the project is moving in the right direction. I had to switch to green tea and bottled water after my first vanilla latte lest I spend more time in the restroom than writing. I am going home to get some shut eye.

Yes I realize email, phones and communication with the outside world is important, but sometimes all you need is a laptop and some peace and quiet.

Monday, July 21, 2003

EJB CMP CMR

Jason Carreira writes in his blog....
" I'm thinking of Entity EJBs here, but the same is true to some extent with JMS and JDO, where all of the really useful pieces for O/R mapping are optional. I accidentally insulted Rick Hightower Thursday night when he was talking about successfully using Entity Beans in a project by saying that his domain model must have been simple…. Sorry about that. What I meant was that a reasonably sized project couldn't use Entity beans successfully without using vendor extensions, and in fact he was. "

First, it was on purpose. :)
Second, I was not offended my skin is pretty thick.
Third, the same arguments can be made against JDO or any other OR mapping solution.
Fourth, I have ported EJB CMP CMR applications to more than one vendors solution.
Fifth, At the time EJB CMP CMR was available, and JDO was not.
Sixth, I am going to try Hibernate on my next green field application.

Jason put your picture in your blog. I can't remember who was who.

Wednesday, July 16, 2003

The reason I changed the title of my blog....


" Announcing Rick Hightower 2.0......




His name is Richard Matthew Lucas Hightower Jr. We are going to call him Lucas.....

(I know... I know.... "Luke I am your father..... Use the force Luke")





Wednesday, July 09, 2003

What skills are marketable

I did a search of Dice to see which skills got the most hits.....

Java 3365
Perl 989
Python 58
Ruby 5
C 2659
C# 500
Struts 162
WebWork 3
WebLogic 554
WebSphere 770
Tomcat 132
Resin 7
Orion 1
SQL 4082
Oracle 3671
JBoss 43
TogetherSoft 20
Eclipse 17
JBuilder 66
WSAD 67
Web Services 1388
JSP 673
ASP.Net 12
EJB 3365
Velocity 37
Ant 74
XDoclet 3
SOAP 207
PORTAL 761
Tapestry 6


The surprise here is how little ASP.Net gets compared to JSP. Now this is not scientific (as if)..... just because Struts gets more hits than WebWork does not mean it is better.... it just means it is a more marketable skill (I suppose). EJB (bitter or not) is still very marketable (more so than JSP).

Monday, July 07, 2003

Bitter EJB and extreme sports

I've been reading Bitter EJB in my spare time.
Amazon.com: Books: Bitter EJB

This is a very thought provoking book. I am about 1/2 done with it. I can already recommend it to all those that will be doing or are thinking about doing EJB development.

Every chapter starts with a short story about the author(s) endeavors in extreme sports.

At first, I found the short stories distracting. As I continued to read the book, I found that they are a nice break from the material that are easily ignored if I choose not to read them.

I am not much of an extreme sports advocate, if I wrote a book like this.... the chapters would start more like this....

"It was a Sunday night, and it was my turn to do the dishes. I know I had to mentally prepare.... "

or

"I was sitting on the couch watching TV. I wanted to change the channel, but this would require looking for the remote... I ended up watching three hours of infomercials instead of finding the remote."

Actually, I did go snowboarding once.... my posterior hurts just thinking about it. My idea of an extreme sport is walking around the block with my kids or playing wiffle ball with my son and daughter. After reading this book, I just might put air into my mountain bike tires and ride around.

Wednesday, July 02, 2003

Observation about Tiles and sharing attributes from tile layout to tile

Observation about Tiles.

When inserting one tile into a page layout tile, The tile that is getting inserted into the page layout tile does not share the variables of the page layout tile scope. They each get there own tile scope.

Thus if the page layout tile is passed a title attribute that title attribute is not passed to the tile (e.g., header.jsp) that dispalys the header. In order to pass the variable to the header.jsp. I must use the tiles:put.

This is because the tiles:insert creates a new component context for the inserted tile (I checked the code and create a debug util to prove this). Thus there is a one to one relationship between component contexts and tiles. (Component context = tile scope for the tile).

The tiles:put allows me to put variable from various scopes if I leave the scope blank it searches all scopes including tile scope (i.e., component context).

Thus to move a variable from a page layout to a tile I would do this:

<tiles:insert attribute="header" ignore="true">
<tiles:put name="title" beanName="title"/>
</tiles:insert>

Random thoughts

Random thoughts

Interesting comments on IOC. It is worth reading if you are new to IOC.

Google Toolbar Installed

Google Toolbar Installed
Google Toolbar Installed

I just installed the Google Toolbar... now I can blog about sites that I visit... even quicker.

Debugging Util for Struts apps

I've been having this nasty little problem. I created a utility to print out various scopes in my app, e.g., tile, page, session, request, application.

I think I have written this same utility several times over the years.....

Here it is..... (maybe I wont loose it this time)....


/*
* Created on Jul 2, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package util;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.JspException;

import org.apache.struts.taglib.tiles.ComponentConstants;
import org.apache.struts.tiles.ComponentContext;

import java.io.IOException;

/**
* @author rhightower
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class DebugUtil {


public static void listScope(PageContext context, int scope) throws JspException, IOException{
JspWriter out = context.getOut();
switch (scope){
case PageContext.PAGE_SCOPE :
out.println("--- Page Attributes ---
");
break;
case PageContext.REQUEST_SCOPE :
out.println("--- Request Attributes ---
");
break;
case PageContext.SESSION_SCOPE :
out.println("--- SESSION Attributes ---
");
break;
case PageContext.APPLICATION_SCOPE :
out.println("--- APPLICATION Attributes ---
");
break;
}

Enumeration enums = context.getAttributeNamesInScope(scope);
while(enums.hasMoreElements()){
String name = (String)enums.nextElement();
Object value = context.getAttribute(name, scope);
printNameValueType(name, value, out);
}


out.println("---------------------------
");

}

private static void printNameValueType(String name, Object value, JspWriter out) throws IOException{
out.println(name + " = " + value
+ " type (" + value.getClass().getName()+ ") " +
"

");

}

public static void listParameters(PageContext context)throws JspException, IOException{
JspWriter out = context.getOut();
Map map = context.getRequest().getParameterMap();
Iterator iter = map.entrySet().iterator();

out.println("--- Request Parameters ---
");
while (iter.hasNext()){
Map.Entry next = (Map.Entry) iter.next();
if (next.getValue() instanceof String){
out.println(next.getKey() + " = " + next.getValue() + "

");
}
else if (next.getValue() instanceof String[]){
StringBuffer buf = new StringBuffer(100);
String[] values = (String[])next.getValue();
buf.append("{");
for (int index = 0; index < values.length; index++){
buf.append(values[index]);
buf.append(",");
}
buf.append("}");
out.println(next.getKey() + " = " + buf.toString() + "

");
}

}
out.println("--------------------------
");
}

public static void listTileScope(PageContext context) throws JspException, IOException {
JspWriter out = context.getOut();
ComponentContext compContext = (ComponentContext)context.getAttribute( ComponentConstants.COMPONENT_CONTEXT, PageContext.REQUEST_SCOPE);
out.println("--- TILE Attributes ---
");


if (compContext!=null){

Iterator iter = compContext.getAttributeNames();
while(iter.hasNext()){
String name = (String)iter.next();
Object value = compContext.getAttribute(name);
printNameValueType(name, value, out);
}
}else{
out.println("--- TILE Attributes NOT FOUND ---
");
}


out.println("---------------------------
");

}

public static void debug(PageContext context) throws JspException, IOException{
JspWriter out = context.getOut();
out.println("
--------------------------
");
out.println("---------D----------------
");
out.println("----------E---------------
");
out.println("-----------B--------------
");
out.println("------------U-------------
");
out.println("-------------G------------
");
out.println("--------------------------
");

listTileScope(context);

listScope(context, PageContext.PAGE_SCOPE);
listScope(context, PageContext.REQUEST_SCOPE);
listScope(context, PageContext.SESSION_SCOPE);
listScope(context, PageContext.APPLICATION_SCOPE);


listParameters(context);

}

}

Eratta for XDoclet tutorial

Thanks for lanuching the new tutorial....

I noticed some errors as follows: (If you send me the latest source, I can make the changes.)


FIRST ERROR:

On the about this tutorial, What is XDoclet page (page 1 of 4)


3rd paragraph last sentence.... it states
This tutorial focuses on using existing templates that ship with XDoclet.

This is incorrect.... it should read as follows

Unlike the last tutorial on XDoclet this tutorial does not focus on using existing templates that ship with XDoclet. Instead in this tutorial, you will create your own custom templates and XDoclet subtasks.


2ND ERROR

Simple template to introduce XDoclet: Servlet XDoclet example (page 1 of 1)
Servlet XDoclet example
should read
Simple XDoclet tempalte example


3RD ERROR

First Template: XDoclet Architecture : Servet XDoclet example

"Servlet XDoclet example" should read "Running Simple XDoclet template example"


4th ERROR

Page 3 of 7 Under Case Study 2nd try: Subclass xdoclet.XmlSubTask

The {0} will be replaces with the name of the current class. Therefore you are going to use a new template that just outputs one class at a time.

should read

The {0} will be replaced with the name of the current class. Therefore you are going to use a new template that just outputs one class at a time.

Developing your own templates and subtask with XDoclet

Developing your own templates and subtask with XDoclet



XDoclet tutorial: Creating your own templates and subtask


This tutorial shows J2EE developers how to use XDoclet to write their own custom templates and subtask. It steps you through three examples. Unlike the last tutorial on XDoclet this tutorial does not focus on using existing templates that ship with XDoclet. Instead in this tutorial, you will create your own custom templates and a XDoclet subtask.

The first example is a very simple example to show how to use XDoclet. The second example shows how to create an Axis Web Service deployment descriptor (WSDD) with just the templating constructs, and how to run this with Ant. The third example show developers how to create their own custom subtask, and refactors the template fore the WSDD with best practices in mind. By the end of this tutorial you will be able to write your own custom XDoclet templates and subtasks. And you will understand when to pass something as an attribute of a subtask and when to put the parameter as a XJavaDoc tag in your source.


----------------------------------


This tutorial shows J2EE developers how to use XDoclet to write their own custom templates and subtask. It steps you through three examples.

The first example is a very simple example to show how to use XDoclet. The second example shows how to create an Axis Web Service deployment descriptor with just the templating constructs, and how to run this with Ant. The third example show developers how to create their own custom subtask, and refactors the template with best practices in mind. By the end of this tutorial you will be able to write your own custom templates and subtasks. And you will understand when to pass something as an attribute of a subtask and when to put the parameter as a XJavaDoc tag in your source.

XDoclet enables simplified continuous integration and refactoring with component-oriented development using attribute-oriented programming. XDoclet allows you to radically reduce development time, by generating deployment descriptors and support code, allowing you to focus on application logic code. Not only can you use the plethora of templates that ship with XDoclet, but you can create your own. In addition you can create a subtask to pass in custom configuration parameters that you do not want to show up in the source files.

XDoclet facilitates automated deployment descriptor generation. XDoclet, a code generation utility, allows you to tack on metadata to language features like classes, methods, and fields using what looks like JavaDoc tags. Then it uses that extra metadata to generate related files like deployment descriptor and source code. This concept has been coined attribute-oriented programming (not to be confused with aspect-oriented programming, the other AOP).

XDoclet generates these related files by parsing your source files similar to the way the JavaDoc engine parses your source to create JavaDoc documentation. In fact, earlier versions of XDoclet relied on JavaDoc. XDoclet, like JavaDoc, not only has access to these extra metadata that you tacked on in the form of JavaDoc tags to your code, but also access to the structure of your source, that is, packages, classes, methods, and fields. It then applies this hierarchy tree of data to templates. It uses all of this and templates that you can define to generate what would otherwise be monotonous support files.

XDoclet ships an Ant task that enables you to create web.xml files, ejb-jar.xml files, and much more. In this tutorial, you will use XDoclet to generate a Web application deployment descriptor with the webdoclet Ant task. In addition you will generate EJB support files. Note that XDoclet Ant tasks do not ship with the standard distribution of Ant. You will need to download the XDoclet Ant tasks from http://xdoclet.sourceforge.net.

So you may wonder: "Why should I care? I am an excellent Java/J2EE Web developer and I have never needed XDoclet". Or you may say: "I already use XDoclet, why do I need to write my own templates?" As I stated before, you don't know what you are missing. Once you start use XDoclet, you will not stop. Once you start writing your own templates you will never repeat yourself again. If you are writing dry, mundane code, then you could probably use XDoclet instead. Allow XDoclet to generate the monotonous stuff, and stick to writing the good stuff. Computers were invented to do monotonous stuff to free humans to do creative things. XDoclet frees developers from monotonous code. XDoclet is the missing piece in your J2EE and Web service development process. It will speed your development. You must master how to use XDoclet templates.


XDoclet tutorial: Creating your own templates and subtask

Tuesday, July 01, 2003

Struts vs. WebWork?

WebWork



I just read through Mikes (mike@atlassian.com) slides comparing Struts and WebWork from the ServerSide Symposium. I am going to get this book as soon as it comes out.... (he one of the authors)


Java Open Source Programming : with XDoclet, JUnit, WebWork, Hibernate (Java Open Source Library)
by Joseph Walnes (Author), Ara Abrahamian (Author), Mike Cannon-Brookes (Author), Patrick Lightbody (Author)





WebOgnl

WebOGNL


I just spoke to Drew Davidson. He is fired up about WebOgnl. Drew is the creator of OGNL which gets used by Tapestry and WebWork. He said that he has rewritten some applications in various frameworks and has noticed a sharp reduction in LOC (lines of code) when using WebOgnl. He is sending me some sample code. As I mentioned before, Drew lives right here in good old Tucson. He is the fastest, smartest developer that I have ever worked with, and I have worked with some really good developers over the years. He is like a power of nature when he develops. He knows everything. And, he is a really big dude. He looks like a professional linebacker (football, american).

WebOgnl is still missing good documentation. Hopefully, it will come out really soon. BTW Ognl is pronounced OGG-NULL. We got in to some debate a the serverside.com symposium on the correct pronounciation of Ognl. I ended the debate with "well that is not how Drew pronounces it". My only claim to fame.... the correct pronounciation of Ognl.

Hibernate

Hibernate


My next project will try Hibernate, an open source OR mapping for Java. I just downloaded the 111 page user guide. Hibernate embraces the fact that it is doing OR mapping, and provides many granular features that are essential to doing OR mapping. Unlike EJB 2.0 and JDO which also do OR mappings, but don't specify how it should be implemented or what types of mappings the implementations must implement. OR mappings standards without the OR mapping in the specification just does not make sense to me anymore. The possible weaknesses of Hiberante is it not standards base (this could also be considered a bonus: read the above comments). Another weakness is Hibernates support for caching not working in a clustered environment.

Sunday, June 29, 2003

TheServerSide.com Symposium

TheServerSide.com Symposium


I had a blast at The ServerSide.com Symposium. I spoke with Gavin King of hibernate fame, Erik Hatcher of Apache Jakarta fame, Howard Lewis Ship of tapestry fame , Mike Cannon-Brookes of OpenSymphony, and a few others to the wee hours of the morning. Being around all of these Java OpenSource leaders has inspired me to get more involved in open source development. Right now I am working on the Mastering Struts book, and then the Java Tools for Extreme Programming 2nd edition. Oh yeah.... I am going to be a father again so I don't know when, but I know I will.

I also want to get up to speed on Hibernate as soon as possible. It seems like something I would use. I currently use EJB CMP CMR 2.x. I am not that thrilled about JDO. This is the one open source project I would be most likely to get involved in.

I currently use Struts for my J2EE web component framework, but in the future I will look into WebWork (part of OpenSymphony) and/or Tapestry. It is interesting that both WebWork and Tapestry use Ognl as their expression language. Ognl was developed right here in Tucson by a guy that Erik Hatcher and I worked with.... Drew Davidson of Ognl and WebOgnl Fame .

I could only stay Friday. I had to leave Sat. It had been a while since I had seen my family. I was in Chicago on biz before I went to Boston. I did read through most of the slides. I kept hearing about Aspects, Aspects, and Aspects! I guess I have to bite the bullet and start messing around with Aspects too.

Some other points of note.... Erik Hatcher gave a really solid talk on Advanced Struts. I learned a few more tricks. Thanks Erik. Vincent Massol of Cactus fame gave a great talk on Unit testing, Cactus and Mock Objects. I did not see his Maven talk, but I did look throught the slides. Maven is defintely something I will use in the near future. Vincent is a genious.

I did not get to see Crazy Bob talk but I read through his slides on JMX and Aspects. Very cool stuff.

All in all, I had a blast at The ServerSide Symposium, The talent level of the speakers was truly stellar.

Wednesday, June 25, 2003

Plastics!

I was in Chicago, and could not get a cab. There was a big plastics convention, and I could not get a cab from the Holiday Inn to downtown Chicago. What a mess!

I tried for 1 hour to get cab.

I ended up sharing a limo with eight other guys. Limos are suppose to be spacious, but they have their limits. I had to practially cross my legs to fit.

When I did get there, I was dropped off at the wrong location. I had two walk a few blocks with a box full of books. What a day.

Monday, June 23, 2003

JavaOne, JavaSoftware Symposium MI WI, Foi Gras and Design Patterns

JavaOne 2003


The last couple of weeks have been hectic. I went to JavaOne in SF, then the Java Software Symposium in MI, and then went to Ohio on biz for a week. I really enjoyed JavaOne. I did not get to attend as many sessions as I would have liked, but it was really fun socializing with the different folks.

I got to meet James Goodwill. I will be contributing to his Mastering Struts book. I also spent some time with Erik Hatcher, Jason Hunter, Sue Speilman, James Duncan Davidson and much more. It was a fun trip. I even met up with my old room mate from my single days. We went to the best French restaurant I have ever been, which was about three blocks from my hotel. WOW! Melt in your mouth Foi Gras (sp?)! I need to figure out a reason to go back to SF so I can eat there again! His ex-wife was a chef for a while, so he knows where to go to find some great food in SF.

The Java Software Symposium was interesting in WI. We got into a very big discussion and on design patterns. My personal feelings on design patterns are that they generally a good thing (a really good thing). However, In the hands of the wrong people that can be disastrous (with a capital D). Yikes! Misapplied design patterns is more dangerous than slapping code together. You can easily design a system that no one can implement by misapplying design patterns. Keep it simple! Start simple.... add complexity as needed and only when needed. There will be enough complexity in the system without trying to use every design pattern in the book whether it makes sense or not. Opinions on this subject were all over the map, but generally it was thought that design patterns are good and get abused and misused. Except for Dave Thomas who thought Design Patterns were in their nature inherently evil or something to that effect. I have a lot of respect for Dave Thomas, but I am not sure I agree with his point of view nor can I repeat it and the depth and insight which he conveyed it. Robert Martin had a very interesting perspective, which I did agree with whole heartedly.

Bitter EJB, Text Processing in Python and BEA WebLogic Bible

Three new books.
I've just got three new books one entitled Text Processing in Python, BEA WebLogic Bible 2nd edition, and Bitter EJB. I've scanned through the WebLogic Bible and the new Python book reading several chapters from each. I think I will read the Bitter EJB book first (it just came in today).

Thursday, June 12, 2003

Just got done speaking at JavaOne.... What a blast

I just got done with my talk at JavaOne.
The room was packed. I got an applause.
People really like XDoclet. I think people will use it.
Using Enterprise JavaBeansTM (EJBTM) Technology on More Projects with CMP, CMR and XDoclet
Java One Presentation
Abstract
I really enjoyed presenting at JavaOne. Everything ran so smooth. Sun really has this down to a science.

Tuesday, June 10, 2003

JavaOne 2003 ---- GOOD

Random thoughts about JavaOne:

JavaOne seems more exciting this year. It seems more optimistic. Last year was kind of a drag. This year there is a positive buzzz....

I ate dinner with Sue Speilman, and the Complete Programmer Network clan. It was a blast.

The Java Fireside chat was nice. I asked a question about EJB CMP/CMR vs. JDO. The answer was unsatisfying to say the least.

The keynote was exciting. Last years keynote was depressing. This years was very upbeat.

I am meeting James Goodwill today to talk abou the next edition of Mastering Struts. I am going to write the chapters on Tiles and the Validator framework.

This year, I most interested in Java Server Faces and JSP 2.0.

They mentioned a JSR on scripting languages in the JVM. I hope this means I can use Python as a scripting langugae with JSP, but I doubt it.

The information on the metadata JSR looks really interesting.

In my spare time I am writing a tutorial on XDoclet, specifically how to write your own templates. I wrote a template last night that generates the deploy.wsdd for Apache Axis.

Questions that I want answered this week:
How will the metadata specification effect XDoclet?
How close is the Java Server Faces event model to ASP.net? (I like ASP.net code-behind, and event model, but don't tell any of my Java friends).
(Liking it an using it are two different things. I still use JSP, and I can't wait to use Java Server Faces).

I really enjoyed the demo in the keynote by Oracle.


There was an interesting discussion about IDE, editors last night, Java language features, Java Server Faces, and mroe.
The luddites in the group (and no I don't know how to spell ludite) were of the opinion that the new language features, IDE wizards and Java Server Faces were bad things.
I am all for making Java easier. I really think the new language features are a blessing. I can't wait to use the new for loop, generics, aut o-boxing, and Enums. (Enums are my favorite.... I really miss them from my C++ programming days). I want the compiler to be smarter and smarter, if it can figure something out and save me from writing several lines of code per method then amen brother. I want my JSP development to be easier and easier as well. I want to be able to drop components on a page and add event wiring. I can develop without these features if needed, but anything that speeds development, I am all for. BTW I love Eclipse and all the plugins and wizards.

I look forward to the presentations on making Java easier, and yes I know Java well, and yes I can program in Java really well, but easier is easier and I am all for easy. I declare this a good JavaOne

Friday, May 30, 2003

Service-enable EJB SessionBeans with Apache Axis and the IBM ETTK

Apache Axis and EJB


This article shows J2EE developers how to use Apache Axis from the IBM ETTK (Emerging Technologies Toolkit) to make any Enterprise JavaBean (EJB) component into a Web service that will run on any application server.

Tutorial link





This tutorial shows J2EE developers how to use the IBM ETTK (Emerging Technologies Toolkit) to make any Enterprise JavaBean (EJB) component into a Web service that will run on any application server.

Do you currently use EJB technology? Have you ever wondered how to expose an EJB component as a Web service no matter what your application server is? This tutorial shows how to use the ETTK and Axis to convert a local and remote EJB component into a Web service. I will use a subcomponent of the ETTK called Axis, a SOAP client implementation originally hosted by the Apache Software Foundation.

The ETTK implements the Web services architecture and provides a set of tools to create, locate and invoke Web services. It includes the following tools:



  • UDDI4J API allows developers to perform save, delete, find, and get operations against a UDDI registry.
    UDDI4J-WSDL API allows developers to perform publish, unpublish, and find operations against a UDDI registry.
    WSDL4J allows developers to programmatically read and work with WSDL documents.



  • WSDLdoc allows developers to automatically generate documentation from WSDL files similar to JavaDoc.
    WSIL4J allows developers to programmatically read and work with WSIL documents.



  • Axis RC1 allows a developer to generate Web services WSDL definitions from Java code and generate Java proxy code from a WSDL definition. Axis is also the transport engine for Web services.



  • Sample services including Accounting, Contract, Metering, Service Desk etc.



  • Demos and tutorials to illustrate key Web service concepts.



  • Privacy Policy Authorization Director (PAD) Web service allows privacy policy control access to personal information.



  • And much more...



If you are serious about Web services then you have to check out IBM's ETTK!


The primary focus of this tutorial is developing EJB-based Web services with Axis. Axis provides support for turning EJB components into Web services and is included with the ETTK.


What this tutorial covers page

This tutorial covers turning EJB components into Web services and has two step-by-step examples. The first example uses all primitive types with one simple EJB component. The second example uses a SessionBean that talks to several EJB components and returns complex types. All examples ship with a set of Ant build scripts so you can easily create your own custom solutions by reusing the sample build files.

This tutorial assumes you have a working knowledge of Java technology and EJB technology. In-depth knowledge of EJB components, Web services, and Ant are helpful but not required to understand the key concepts. Ant is used to build and deploy the example applications. Reference to introductory material on Ant, Java technology, J2EE, Web services, XML, and EJB components are provided in throughout the tutorial and at the references section at the end of this tutorial.

The source code in the tutorial has been tested with Resin EE application server.

The applications should be easy to port to other J2EE-compliant application servers like IBM WebSphere or JBoss. Please check back at my site for ports to other application servers (see Resources).

I typically get examples from people working with other application servers, and then I put them up on my site (see Resources).

I used the Eclipse framework to create the examples in this tutorial. The examples are easiest to run by downloading Eclipse 2.1 or higher and a J2EE application server plug-in for Eclipse. Eclipse has excellent support for Ant, which facilitates running the Axis and XDoclet Ant tasks right from the IDE environment.

If you are new to Ant, please read this sample chapter from Mastering Tomcat on Developing Web Components with Ant (written by yours truly). Just read the sections on Ant development for now.
Using Ant

Also note that the Ant scripts can use XDoclet. You will not need to use this functionality, but, in case you decide to, please refer to the developerWorks tutorial, "Enhance J2EE component reuse with XDoclet" (see Resources).

Wednesday, May 21, 2003

Speed J2EE component development with XDoclet

Speed J2EE component development with XDoclet


I wrote a tutorial on XDoclet for IBM developerWorks.

"This tutorial shows how to speed J2EE development with XDoclet. Why write five classes and three deployment descriptor when you can write one and generate the rest? This tutorial consists of step by step examples using XDoclet with Servlets, Custom Tags and EJB (with CMP, CMR 2.0). XDoclet is an open source project that aids in the development of J2EE components."

DeveloperWorks article
Java Channel link to tutorial
JavaRanch link to tutorial
JavaLobby link to tutorial

Sunday, May 04, 2003

JDJ this month: Good Articles this month

Picked up a copy of the JDJ this month. What a great issue! I am really enjoying reading about in container caching, although I don't 100% agree with the conclusion. I believe the results she got, but I don't agree that that is the type of thing you usually cache. I thought the article could have spent more time talking about when/why to use caching instead of making up a contrived example that would obviously break. And, although I did not agree with the conclusion, I really found the article interesting. I've run into problems with caching before. I have had similar experience that the article was talking about. A little caching good.... too much is evil. Be careful what you cache. It can be great. Too much and it can kill.

I browsed the rest of the magazine. There seems to be some good articles on Abbot and Big Brother (CI tool). I look forward to reading these as I fly from AZ to Minnesota on Tuesday. Has anyone tried using caching against a RAM Disk? I was going to try this on a project, but decided to cache some results on HD and small frequently used data in a weak hash map instead. The important thing is that I knew how much the data would grow (the upper limit). I'd like to try the RAM disk approach (with a LRU type cache) so the garbage collector would not have to manage the memory. Hmmmmmmmmmmm.....

Hmmmmm..... I noticed my resume comes up second when searching for Rick Resume I love google

Click here and look at the second link

Rick Resume

Saturday, May 03, 2003

Get Tomcat book examples working for Xdoclet 1.2

Get Tomcat book examples working for Xdoclet 1.2
Upgrade examples to the lastest version of Xdoclet (xdoclet 1.2)
Finish writing/updating tutorial
Add EJB support....from previous work.
sounds like a lot of work.

Find the files move them over... then port. Start with the Servlet example and Custom Tag example. Upgrade to latest ant first.

I changed the script to use a path instead of putting a list of jars in the build.properties.

Upgrading example to 1.2 from Xdoclet 1.1 problems:

1) the webdoclet task no longer supports sourcepath. I removed it from the example ant script.

2) xdoclet.web.WebDocletTask is deprecated. I changed the taskdef to use xdoclet.modules.web.WebDocletTask

After that everything worked groovey.I came up with an idea. An Ant task that takes an eclipse .classpath file (which is just an xml file anyway) and adds every item to the classpath. This would make things a little easier.when working with eclipse. Hmmmm....

Tutorial for IBM, toot-o-matic

I am working on a tutorial for IBM. My laptop crashed since the last time I wrote a tutorial. I have a new laptop. I need to reinstall all of the software to write the tutorial. You write the IBM tutorials in XML then use a tool called Toot-o-matic from IBM to convert it to HTML and PDF format. The tool is open source and uses XSLT.

I wrote a preprocessor that coverts a text file into the XML file in jython so that I can use the spell checker and grammar checker of MS Word before I make a fool of myself.

I have to download jython, toot-o-matic, and who know what else to get this

started.... here we go....

Doug Tidwell is too funny.... I am looking for a download link for

toot-o-matic and I ran into his bio....


About the author
MC Dug-T is developerWorks' Minister of Science, droppin' the XML, Java,

and Web services 411 on the public. In his travels, he gets mad props from

his peeps worldwide for the stone-cold, stoopid-fresh style sheets he leaves

behind. All his mad-phat nollidge will soon be published by O'Reilly and

Associates in the Strictly Non-Fiction book XSLT (ISBN 0596000537, pre-order

your copy today at amazon.com) which will then start slayin' soft-sellin'

suckas at tha local booksella. Discussing the book in a recent dW interview,

he boasted, "I'm gonna empty mah dome into one supa-fly tome."
For relaxation, he likes to put his hands up in the air, and in his words,

"wave 'em around like I just don't care." When not chillin' with his

worldwide XML krew, he maxes at the crib in Raleigh with his wife, cooking

teacher CT-ONE, and their six-year-old shortie, Lily the Flayva Princess.

You can send him a shout-out at dtidwell@us.ibm.com.


How funny is that? :)

The tutorial link for toot-o-matic
http://www-106.ibm.com/developerworks/library/x-toot/index.html

Here is the download link from the tutorial
https://www6.software.ibm.com/dl/devworks/dw-tootomatic-p

There are two download files.... jars.zip and tootomatic.zip...
Hmmm... jars.zip is ten times bigger than tootomatic.zip
better get them both.

now what... no instructions....

Ahhh... the directions are in the tootomatic.zip file....

here they are....
****************************
Installing the Toot-O-Matic:

To install the Toot-O-Matic, unzip the files tootomatic.zip and jars.zip

into the same directory on your hard drive.

Toot-O-Matic uses the Java 2 SDK, 1.3.0_02. You can download it from
http://java.sun.com/products/archive/index.html.
****************************

now i need to install jython...
http://sourceforge.net/project/showfiles.php?group_id=12867&release_id=67726


it looks like tootomatic changed since the last time I used it...
now they are using XML Schema instead of dtds... hmmm....
my xml tut files don't work anymore... hmmm...
looks like i can use either dtd or xsd... i'll stick with dtds for now.

my preprocessor sticks the wrong dtd location in the file....
quick change. no problem... i am up an running.

Looking for an eclipse plugin that support XDoclet and finding all kinds of other stuff too

I want to checkout Easy Struts, the JBoss IDE, and Lomboz , and this http://sourceforge.net/projects/javacodemaker.

The last one does not appear to be fully baked... yet.

Anyone tried any of these.....

Hmmmm..... unrelated....
Jdepend does metrics… do we want this…. ???

Here is an article I plan on reading regarding EJB testing.... Automating EJB Unit Testing.
See if he has similar thoughts than I do on this subject.... maybe catch an aha or two in the progress.

and just for kicks.... i want to check out http://sourceforge.net/projects/xpetstore/. This is a project I would like to get involved in.... after I am done with EasyEJB 1.0 release.

Another tool i am dying to try out is MiddleGen.... http://sourceforge.net/projects/middlegen/

Hmmm... i want more eclipse tools.... i need a UML plugin, a database plugin and a good xdoclet plugin.....

JDJ Mag..... CD packed full of articles

I got my new JDJ Mag with the CD of every article ever written by the JDJ.
I was searching for article I wrote when I ran accross this.....

It was a show report by Stephen Berkowitz:

"I would be remiss if, in the focus on Web services, I failed to point out that the conference also had a Java focus. The best Java presentation I went to was given by Rick Hightower of Trivera. His talk on "Java Tools for Extreme Programming" was well presented and rather informative. Rick focused on the testing and continuous integration portions of XP, discussing JUnit, Ant, and Cactus in detail. His talk proved to me that no matter what you are doing, no matter what you call your methodology, testing is invaluable and that these tools will make your life easier. "

Excellent. I am glad you liked it.
This was my first presentation in a long time, and I was pretty nervous.

Friday, May 02, 2003

Custom Tag

Last night (yesterday) I wrote a custom tag for the Struts course, and wrote a Cactus test for it.
The custom tag prints out a value of a property from an EJB. It is called EJBWrite.
It is like BeanWrite (a struts custom tag), but different.

It uses BeanUtils, ResponseUtils, RequestUtils, and Property Utils. (three birds.... one stone)

I also dug into WSAD for several hours. I am becoming an expert. If you love Eclipse, you will go ga ga over WSAD

Speaking at JavaOne... Info....

Speaking at JavaOne! Yeah!

Using Enterprise JavaBeans(TM) (EJBTM) Technology on More Projects with CMP, CMR and XDoclet TS-3198
Speakers: Rick Hightower
Thursday Jun 12, 1:30 PM - 2:30 PM, Esplanade 301, Moscone Center

There has recently been a lot of discussion about whether or not to use Enterprise JavaBeans(TM) (EJBTM) technology. This session shows that EJB technology can be used on many more projects than it is currently. The argument against using EJB technology tends to be that it is too complex. This is ironic since EJB technology's purpose was to simplify server-side development. While it is true EJB.....

This is the first time speaking at JavaOne. I was part of a BOF once. I was on a BOF panel. And, I've had booth duty for three different companies at JavaOne, but never a session. I am stoked!

Thursday, May 01, 2003

I really dig StrutsTestCase

I really dig StrutsTestCase


It took me a while to get things installed and configured, but it was worth it. (StrutsTestCase in not compatible with the version of Cactus that the Eclipse Cactus plugin in uses..... this was one of the many issues I ran into.)

StrutsTestCase allows you to easily test StrutsActions:

Check out the following code listing:


public class EditEmployeeActionTest extends CactusStrutsTestCase {



/**
* Constructor for EditEmployeeActionTest.
* @param arg0
*/
public EditEmployeeActionTest(String arg0) {
super(arg0);
}

/*
* @see TestCase#setUp()
*/
public void setUp() throws Exception {
super.setUp();
}

/*
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}

public void testEditEmployeeAction () throws Exception{

/* Create the test employee */
String firstName = "Bob";
String lastName = "Jones";
String phone = "555 1212";
Integer id = Util.createTestEmployee(firstName, lastName, phone);

/* set the path to the EditEmployeeAction's path */
setRequestPathInfo("/editEmployee");

/* set the employee id to load */
addRequestParameter("id", "" + id);

/* Force the action to occur */
actionPerform();

/* Make sure the action forwarded to the form */
verifyForward("form");

/* Get the EmployeeForm from the request attribute */
EmployeeForm form = (EmployeeForm) request.getAttribute("employeeForm");

/* See if it is in edit mode */
assertEquals(EmployeeForm.EDIT_MODE, form.getAction());

/* Make sure this is the right employee */
assertEquals(firstName, form.getEmployee().getFirstName());
assertEquals(lastName, form.getEmployee().getLastName());
assertEquals(phone, form.getEmployee().getPhone());

Util.killTestEmployee(id);

/* Make sure there are no errors */
verifyNoActionErrors();

}

}

Wednesday, April 30, 2003

Studying WebSphere 5

WebShpere Architecture overview:


Base configuration means seperately administered.

A node is a group of managed WebSphere servers that share configuration.

Configuration repository is in XML.

PMI stands for Performance Monitoring Interface.

In the base configuration the adminconsole runs on the one app server.

In the network deployment configuration, the adminconsole in run on the Deployment Manager.

Each server has an Admin Service.The Admin Service stores xml config files local to the server.

wsadmin allows the adminstration to be scripted.

JMS is used for intra cell communication. It is also used for in memory session replication.

There can be several nodes in a cell.

In the base config, JMS runs in the same machine as the server.

In the network deployment config, JMS runs in a dedicated JVM.

Session data can be stored in a database or replicated from server to server in the case of a network deployment. The server to server replication is done interanlly with JMS.

JNDI for WebShpere is built on top of CORBA CosNaming.

Security is not covered in this redbook, if I want to read about security I need to read IBM WebSphere V5.0 Security Handbook, SG24-6573.

Web Services in not covered in this redbook. If I want more information on WebShpere web sevices I should read WebSphere Version 5 Web Services Handbook, SG24-6891.

A network deployment consists of multiple Nodes.
A Node consist of a node agent process and several application servers.
The app servers in a node are managed by an adminstrative cell by the Deployment Manager process.

Clusters of load-balanced application servers are configured with the Network Deployment cell.

The Deployment manager sychronizes the binaries (code) and config (deployment descriptors) of every component to local copies of every node. The DM stores the binaries and config for each component in the master config repository. The DM talks to the Node agent to coordinate and synchronize management operations.

A cell is a node group for admin purposes.

The UDDI Registry is not covered in this redbook. For detailed information on the Web services support in WebSphere Application Server V5, see WebSphere Version 5 Web Services Handbook, SG24-6891.

The Web Services Gateway is not covered in this redbook. For detailed information on the Web services support in WebSphere Application Server V5, see WebSphere Version 5 Web Services Handbook, SG24-6891.


The edge components consist of the cacher and the load balancer.

The load balancer manages site selection, workload management, session affinity, and transparent failover.


The caching and filtering component are used for recieving request and serving URLs. The nice thing about the cacher is that it is programmable. Thus you can customize when the cache will be invalidated.

Follow up reading on caching and filtering:

Patterns for the Edge of Network, SG24-6822

WebSphere Edge Server New Features and Functions in Version 2,
SG24-6511

The concept of cluster is divorced from cells and the deployment manager. The only req. for a cluster is that they serve the same application. It could be a laptop and a server is the example they give. The configuration does not have to be identical. A cluster is just to provide failover support and workload balancing not duplicate config.

JMS Server, App server, Node agent, and the Deployment manager are all managed services via JMX.


Topology Selection:

I read the entire topology section. I need to reread this. There is a lot of info I want to go over.
I've read the first 103 pages of the admin book. Hmmmm.... only 900 more pages to go.

EasyEJB: Struts CRUD framework, getting started....

Status:


I figured out how to use CVS with SourceForge.
I figured out how to upload the main website.
I updated my project to use Eclipse 2.1 and started using the new Resin EE and Cactus plugin.

The Cactus plugin was a wash for me. It uses Jetty, and I am not to interested in that. The Cactify feature was nice and useful, but I resorted to using the cactus.properties file. I am really enjoying the JUnit/Eclipse integration.

I am impressed with the Resin EE plugin from Improve. I need to adjust Resin to reload classes more often. I have been resorting to restarting it often.

I wrote the tests for the new class that was EJBUtils now renamed to LocalFinderUtils. Here is a sample of what you can do with LocalFinderUtils:



//The default context is set to java:comp/env/ejb. You can override the default or set a new default.

//Find a single bean by primary key
Dept dept = (Dept) LocalFinderUtils.findByPrimaryKey(pkey, "DeptBean");

//Find a collection of entities
Collection collection = LocalFinderUtils.findAll("DeptBean");

//Find a collection of entities by dept name that start with eng (one criteria)
Collection collection = LocalFinderUtils.findCollection("findByDeptNameLike", "eng", "DeptBean");

//Find a single entity by dept name (many criteria supported)
Dept bean = LocalFinderUtils.findObject("findByDeptName", new Object [] {testName}, HOME_LOCATION, "DeptBean");


There are many more variations of the above (12 so far).
Making the code generic (something we did not have to worry about at eBlox) for general consumption is time consuming.
I wrote tests for the above. In order to do that I had to include a few EJBs (Dept and Employee).
I spent a lot of time writing JavaDocs. The tests turned out well.

I changed EJBUtils (after the rename) to use MethodUtils from the BeanUtils commons project as Apache. I was caching my own method calls. At some point in the future, I want to benchmark EJBUtils (used cached method calls) against the new version vs. accessing the home method directly. Hmmm.....

I am going to document TransactionUtils, write the tests for it, and push it out. Nick L. wrote transaction utils (as far as I know).
Here is an example usage of TransactionUtils. I don't have a published test.


TransactionUtils.runInTransaction(
new Runnable(){
public void run(){
try {
Dept dept = (Dept) home.create(testName);
pkey = dept.getId();
}catch (CreateException ce){
throw new EJBWrapperException(ce, "unable to create Dept");
}
}
}
);


Task list before Alpha release



  1. Incorporate EJBUtils and TransactionUtils (almost done) (document, test)

  2. Incorporate EJB plugin I wrote for Struts (document and test)

  3. Include and refactor EJB CRUD framework. Change to use LookupDispatchAction action. Get it working in a more genric manner wrt to keys. Old verions only works with int and Integer keys. This can be improved! Write tests, and javadocs(document and test)

  4. Create base classes for EJB types and classes (PK key, Entity and Session for this release) (document and test)

  5. Create EJB Home Cacher for locals and remotes (document and test)

  6. Modify plugin to use new utilities EJB Home Cachers and Transaction Utils (document and test)

  7. Make plugin Struts modules aware (document and test)

  8. Move 5 custom tags for dealing with EJB (document and test)



Tuesday, April 29, 2003

Strtus CRUD framework

I came up with an Idea for a Struts based, EJB CRUD framework when I worked at eBlox. We wrote it. Andy, Ron, Nick, and Paul contributed to it.
I got permission from Andy to make it open source. I need to clean it up a bit. I have been working on it every night for a few hours (for the past two nights).

I doubt I will be able to give it the attention that it needs. I want to get what is there working. I want to clean it up a bit. I will keep working on it until it at least equals what we had.

Anyway, I started a Sourceforge project and committed my first three files.

Your project registration for SourceForge.net has been approved.

Project Descriptive Name: EJB Utils (Struts based CRUD framework)
Project Unix Name: easyejb
CVS Server: cvs.easyejb.sourceforge.net
Shell/Web Server: easyejb.sourceforge.net

I started setting up my env. for development. I upgraded to Eclipse 2.1. I had to reinstall XMen, and the Resin plugin. I decided to use the new Cactus plugin. I've been playing around with it and other plugins. I just got Eclipse working with CVS. In the past, I always used WinCVS. I could not get WinCVS to talk to the source forge CVS server so I fooled around with the Eclipse CVS support. Very Nice!

Anyway, this is what I plan to be doing in my spare time.

I just put the new proposal in for Java Tools for Extreme Programming the 2nd edition.

Tuesday, April 22, 2003

Best Practices

Here are the slides to the well recieved Principles and Practices of Effective Developers

http://www.rickhightower.com/BestPractices.pdf

JavaOne!

I just got accepted to speak at JavaOne on EJB CMP CMR and XDoclet. Apparently I was on the runner-up list, and someone canceled. I am really psyched!