31 May 2005

28 May 2005

Hey! Weblogic is not a piece of crap

It's a humongous pile of shit! Every single day, every depths I explore on this application server, the stronger the stench gets. I am telling you guys, the further you go with this product, the further you lose control, the quicker you lose your freedom of choice on tools, frameworks and so forth meaning the higher your maintenance cost go up and the longer your development time goes too. Just simply deploying a .war file that uses a different web framework and a different rendering framework (other than JSP) will take a lot of work.

I guess the Weblogic people treats every developer with utmost stupidity, they assume that developers does not know or use MVC(all types) so they offered Workshop so a hapless developer will code his/her business logic directly to JSP and sooner you'll see a JSP code that is bloated and freakingly slow. So when this hapless developer becomes enlightened and want to switch to a better framework. Weblogic, is not ready for it. Hey, my world does not revolve around Weblogic, it MUST be the other way around.

In another thought, I would like to praise Sun Microsystems for the job well done on Sun Java System Application Server Platform Edition 8.1 2005 Q1 Release, great improvement from the past versions. Good use of open source tools, straightforward look and feel, does not require a JVM plugin for its web admin console. What's best every applications like .war, .ear, .jar can be seamlessly deployed to it's container. I would like to praise its Stand-Alone Container Architecture where it gives developer ability to execute stand-alone applications within the container, The LifeCycle Container is also a good place to deploy your non-EJB business objects, it's so useful to me because I AM NO EJB FAN. The downside is, they should really get rid of this JES product. It stinks like Weblogic.

25 May 2005

They know the future and they are very, very afraid

"Fear of Loss is the path to the Dark Side" -Yoda

And from the looks of it they are losing. Project Grasshopper is a Mono-based plugin for Visual Studio .Net to help sissy developers write applications for Linux and even J2EE! Would you believe that? Why? What's the value of Linux and J2EE and even the Open Source in general these days? I think it's relatively huge, and it's natural for the Dark Side to feel the Fear of Loss. What happened to Microsoft's JUMP(Java Users Migration Path)? I've heard this JUMP when I was at Microsoft Business Solutions before, but it seems things are not happening as expected. Of course, the great excuse for this is M$ still wants to get a large piece of the server-side pie which makes more money than his desktop craps these days. Imagine, Linux desktops are getting closer and closer to Windows in terms of user-friendliness and functionality. By the way there's a Linux version of the America's Army, which means in the near future the game developers will providing different OS versions of their games. Since mostly, games are just one of the few survival cards Windows is holding these days. Take that away and we'll live happily ever after.

So why not just let .Net deliberately drive Windows to the dead end and save more money? And someone predicted that Microsoft will be reduced to just a plugin/utility company someday and maybe it starts now.

Loading the Properties with Classpath resource

This technique is the most taken-for-granted technique by some advanced users. But I see some developers who still use the java.io.File when loading properties which is very difficult or even impossible to adapt when your APIs are being called from stand-alone to web applications or even to the application server's lifecycle container. So much for talk, I'll show you a 10-minute code on how to do this.

Listing 1: Is the properties loader class called PropertiesLoader.java



/*
* Created on May 25, 2005
*
*/
package props.sample;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

/**
* Shows how to load the properties with classpath resource
*
* @author Jared Odulio
*
*/
public class PropertiesLoader {

private Properties props;
private String property;

/**
*
*/
public PropertiesLoader() {

initialize();

}

private void initialize(){

try {

props = new Properties();
InputStream is = this.getClass().getResourceAsStream("/conf.properties");
props.load(is);

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

/**
* Returns the property value from a given key.
*
* @param key
* @return
*/
public String getProp(String key){

property = props.getProperty(key);
return property;

}

/**
* Lists the property value to the output stream.
*
*/
public void getProps(){

props.list(System.out);


}
}




Note the class uses the getResourceAsStream() that looks up the application's classpath.

Listing 2: The main executable, MainProps.java



/*
* Created on May 25, 2005
*
*/
package props.sample;

/**
*
* The main executable.
*
* @author Jared Odulio
*
*
*/
public class MainProps {

public static void main(String[] args) {

PropertiesLoader pl = new PropertiesLoader();
System.out.println("Getting a property key = my.key:");
System.out.println("Property is " + pl.getProp("my.key") + "\n\n");

pl.getProps();

}
}



From here, we simply use the PropertiesLoader class.

Listing 3: The properties file called conf.properties



my.key=this_is_the_value
my.anotherkey=anothervalue



To execute this program we simply specify the location of the conf.properties to the classpath either by modifying the CLASSPATH environment variable or specifying the JVM arguments at runtime by doing this:



java -cp <LOCATION_OF_THE_PROPERTIES_FILE> props.sample.MainProps



The result will be:



Getting a property key = my.key:
Property is this_is_the_value


-- listing properties --
my.key=this_is_the_value
my.anotherkey=anothervalue



This technique has been proven to work anywhere whether it's stand-alone application, web or distributed application sitting on top every J2EE compliant application servers like Sun App Server, Weblogic, Websphere, JoNaS, JBoss etc. etc.

23 May 2005

Long Weekend (Vesak Day)

I hope it's longer :)), but really, long weekend is relaxing and fun, and when you're having it, time does fly.

So I started the long weekend last Friday at Crazy Elephant at Clark Quay. Clark Quay is more like Greenbelt 3, Libis, The Fort etc. etc. all put together along the river side. Warren and I got our dose of a local band's Blues renditions from Eric Clapton, Jimi Hendrix and so forth. The Blues crowd in Singapore really dances to the blues! Which I haven't seen in the Philippines where you only see bobbing heads and tapping shoes.

Afterwards we went to Jazz@Southbridge, this one is just located across the river at Boat Quay. It's past 1 am hoping to catch up the last gig, and lo! When I got inside I thought the music was only being piped out from a CD player hidden some place else because I haven't seen a band playing. After a taking few more steps further inside, I saw the source of Sound, the Altar of Jazz, YES it's jazz, raw and alive with David Gomes, Fabian Lim, Eddie Jansen and Tan Boon Gee. Blues and Jazz, people, are real "serious" stuff, notwithstanding, Classical as well. Children with musical inclination, usually with these types of genre, can tackle mathematical problems with little effort than others. This is called by some experts as interplay between music and math. I think it's a kinda true, some hardcore techie that I know have this kind of interplay. Solutions to tech problems just flows out of them seamlessly. So get your kids into the program!

And I got home at wee hours of the morning, thanks to my Visa Electron, I am practically cashless all through the night. And I used it even to pay for my taxi to home.

Saturday, nothing much just slept all day. Sunday, finally I am going to consumate my Star Wars booking at Eng Wah Cinema Suntec. Almost all is great, 2K digital experience whatever that means but honestly, no pun intended, those chinese subtitles should be smaller as they are really distracting or better yet; don't put it all since most Singaporeans who were born between 1960 and the first showing of Episode VI (Return of Jedi) around '83 can understand English at least. Just have those subtitles on DVDs instead.

And Monday, just walked around shooting with my K700i, I should have waited for the Treo 650 on Septemper. But I just realized that I don't want to add work on my pocket, since it's already in my bedroom as well. And it's not an extension of my manhood :))

17 May 2005

Hibernate is nothing but noise

The blog that won the ire of Christian Bauer. On it's one year anniversary. I'll be reposting it.

All noise less power. This is an SQL view written in Oracle as an example that can be queried by a JDBC in a no brainer manner:



CREATE OR REPLACE VIEW V_DECIMAL AS
SELECT ((50000 / 1000) * .525) AS COMPUTATION FROM SYS.DUAL;





Now, let's query this view within SQLPlus or TOAD or TORA or Quantum or JFaceDbc or whatever SQL editor you have.



SELECT * FROM V_DECIMAL;





And the output would be:




+---------------------+
|COMPUTATION |
+---------------------+
|26.25 |
+---------------------+






Now doing it in Hibernate will require a persistent object like this:




public class VDecimal{

Long computation;

public VDecimal(){

}

//Since it's a view and 'computation' is not a real column, Hibernate does not have a clue if the actual datatype is a decimal or not.
//So the mother of all screwups will think the most obvious data type.
public void setComputation(java.lang.Long computation){

this.computation = computation;

}

public Long getComputation(){

return computation;

}
}







Of course that lousy VComputation.hbm.xml file is needed all the time that will look something like this:


<!--Since it's a view and "computation" is not a real column, Hibernate's dumb tools can't generate an id tag, sorry...-->
<property name="computation" (...the rest of here will probably be a generated guesswork)/>




Because of these I was tempted to "cheat" the ID tag, to lessen Hibernate's embarassing situation with an end-user and proceed to the querying code. What I chose were two styles, the "proper" way and the typical way:



//"proper" way
VDecimal vdec = null;
Session session = creation session blah blah blah....;
Query query = session.createQuery("from vdecimal in class VDecimal");
Iterator iterate = query.iterate();
while(iterate.hasMoreElements(){
Obect tmp = iterate.next();
vdec = (VDecimal)tmp;
}
System.out.println("I am supposed to show up: " + vdec.getComputation());


//the typical way:
List letse = session.find("from VDecimal decimal");
vdec = (VDecimal)letse.get(0);
System.out.println("Chances are this might show up: " + vdec.getComputation());





Using a Query interface, the above will return a decimal but for the lack of foresight will throw "QueryException: invalid alias 26.....".

Since we might be stupid enough and can't fix it then what the heck it's a step backward anyway. So much with this sad story but before some Pampers Kids will criticize SQL views here, this is what I am going to tell you. For the nth time, this is a pathetic struggle to avoid SQL tweaking. For decades, views has been fixing complex table joins, they can break it down into smaller set of relevant queries to create hundreds relevant virtual tables that does not require unloading and reloading everytime it is accessed and RDBMS like Oracle and PostgreSQL can perform this in a snap. I watch in aweful disappointment on my Tomcat logs the "binding and mapping" dance Hibernate does for a simple query even if its only during first run. And I watch in aweful disgrace when I see others will almost kneel and kiss the ground when they see this dance happening over and over again.Torque, I might say is a bit simpler, once you've created your persistent objects, there's no need to reference the XML document that was configured to build the schema and the class that was mapped to it. But so much with this O/R Mapping crap.

Of course, the same old rule is still in force: "If your data structure is a screw up, your application is no different". Hibernate is not an excuse to have lousy database design, it will not reverse a database design failure. An application with a good DB foundation will run seamlessly with or without Hibernate. Views and if necessary, stored procedures and functions still packs some power punches, so learn to use them and learn to love them. Why be worried from "learning" something else aside from Java alone? Because this is the only consistent excuse I've heard and read from O/R mapping advocates. Very shallow reason.


All in all, JDO ROCKS! DAO Pattern Rocks!

Do you still use notify() and wait() explicitly?

As some other people will say Threads can be your best friend or worse enemy...that is, if you're still entangled with your synchronization and you're still hand coding your notify() and wait() statements and still wondering where to put them. OR do you still create your own Thread objects and execute them yourself?

Thanks to Doug Lea's Concurrent API, synchronization becomes a breeze. One of the most useful is the LinkedQueue class which is an implementation of the Channel Interface. To get a glimpse of what it does, first let's build a sample code. This snippet will simply try to perform a JMS-style send-and-listen message pass. First the take() method will be initiated and "waits" for the message to "come in" via the put() method.



import EDU.oswego.cs.dl.util.concurrent.Channel;
import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;

/**
* Description:
*
* @author Jared Odulio
*
*
*/
public class ConcurrentTest {

private Channel channel;
private String message = "Bobsled";

/**
*
*/
public ConcurrentTest() {
super();
channel = new LinkedQueue();

}

public void takeME(){

try {
String taker = (String)channel.take();
System.out.println(taker + " just slided in...");
} catch (InterruptedException e) {

e.printStackTrace();
}
}

public void putME(){

try {
channel.put(message);
} catch (InterruptedException e) {

e.printStackTrace();
}
}

public void initialize(){

Taker take = new Taker();
take.start();
System.out.println("Taker started");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Putter put = new Putter();
put.start();

}

public static void main(String[] args){

new ConcurrentTest().initialize();

}

class Putter extends Thread{
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
public void run() {
// TODO Auto-generated method stub
putME();
}

}

class Taker extends Thread{
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
public void run() {
// TODO Auto-generated method stub
takeME();
}
}
}





And the output would be:



Taker started



And after 3 seconds:



Bobsled just slided in...

Java Job Scheduling Using Concurrent API

Just rescuing some valuable blog entries.

Simplicity and better control are my main reasons for choosing ClockDaemon from Doug Lea's Concurrent API that will be included in the JDK 1.5 Tiger over OpenSymphony's Quartz component. I won't be talking about it much as to why is it so. Hopefully, a code sample and common sense can give clarity to the unenlightened. The sample uses only one the most useful administrative methods for scheduling, the executePeriodically().



import EDU.oswego.cs.dl.util.concurrent.ClockDaemon;

/**
* Description:
*
* A simple job scheduler.
*
* @author Jared Odulio
*
*
*/
public class Scheduler {

private ClockDaemon clockDaemon;

public Scheduler(){
clockDaemon = new ClockDaemon();
}

public void startJob(long periods){
clockDaemon.executePeriodically(periods, new Job(), true);
}

public static void main(String[] args) {

long periods = Long.parseLong(args[0]);
new Scheduler().startJob(periods);

}


class Job implements Runnable{

/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
// TODO Do something here. like write to log file etc...
System.out.println("Scheduled job has been triggered");

}
}
}





Of course, the code is not in a extremely good format(the use of inner class) for it to be "copied-and-pasted" on anyone's production project. But the point of this sample is the ClockDaemon API. I still hope the "expert" or some self-righteous-and-the-only-one-he-thinks-knows-everything American Software Architect would criticize on the point of this article.

The XWork Validation (Restored)

I thought I lost this blog entry forever.

Restoring now...

With some words snipped from jcarreira.

The Xwork Validation Framework is designed to help apply simple validation or custom validation rule to Action before it is executed.

The Validator framework, at its core, takes just an object and a String context name for which to validate that object. This allows you to have different validations for the same class in different contexts. You can define default validations in the class-level validation file (ClassName-validation.xml), and then define validations which are added on top of these for a specific context (ClassName-contextName-validation.xml). In the case of Action validation, this context is the Action alias. The validators are applied in the order they are listed in the validation files and error messages are saved into the Object (if it implements ValidationAware). Note that ClassName-validation.xml must be at the same package of the Action class. Here is an example of ValidateAction-validation.xml that defines rules of validation:



<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">

<validators>
<field name="name">
<field-validator type="requiredstring">
<message>You must enter a value for name</message>
</field-validator>
</field>
<field name="email">
<field-validator type="email">
<message>You must enter a value for email</message>
</field-validator>
</field>

<field name="birthday">
<field-validator type="requiredstring">
<message>You must enter a value for Birthday</message>
</field-validator>
</field>

<field name="tin">
<field-validator type="requiredstring">
<message>You must enter a value for TIN</message>
</field-validator>
</field>

<field name="url">
<field-validator type="url">
<message>You must enter a value for URL</message>
</field-validator>
</field>


<field name="duns">
<field-validator type="duns">
<message>You must enter a value for Dun and Bradstreet number</message>
</field-validator>
</field>

</validators>




To explain further, Here we can see the configuration of validators for the ValidationAction class that we will discuss later. Validators (and field-validators) must have a "type" attribute, which refers to a name of a Validator registered with the ValidatorFactory(see discussion below). Validator elements may also have <param> elements with name and value attributes to set arbitrary parameters into the Validator instance. A sample of param element can look like this:



<field name="date">
<field-validator type="date">
<param name="min">12/22/2002</param>
<param name="max">12/25/2002</param>
<message>The date must be between 12-22-2002 and 12-25-2002.</message>
</field-validator>
</field>




Note that the processForm() will not be executed before the ValidationInterceptor has not yet intercepted all necessary validators.

The ValidateAction.java



package com.ingenium.xwork_validation;

import com.opensymphony.xwork.ActionSupport;
import com.opensymphony.xwork.ValidationAware;


public class ValidateAction extends ActionSupport implements ValidationAware {

private String whom;
private String message = "";
private String name = "";
private String email = "";
private String url = "";
private String birthday = "";
private String tin = "";
private String d_and_b_number = "";
private String zip_code = "";

private String validationAction = "ShowForm.action";

public String getMessage() {
return message;
}

public void setName(String name){
this.name = name;
}

public String getName(){
return this.name;
}

public void setEmail(String email){
this.email = email;
}

public String getEmail(){

return email;

}

public void setUrl(String url){

this.url = url;

}

public String getUrl(){

return url;

}

public void setBirthday(String birthday){

this.birthday = birthday;

}

public String getBirthday(){

return birthday;

}

public void setTin(String tin){

this.tin = tin;

}

public String getTin(){

return tin;

}

public void setDuns(String dunscode){

this.d_and_b_number = dunscode;

}

public String getDuns(){

return d_and_b_number;

}

public String processForm() {

if (!hasFieldErrors()){

return INPUT;
}

if (!hasErrors()){
return INPUT;
}
return ERROR;
}

public String execute() throws Exception {


if (!hasFieldErrors()){
return SUCCESS;
}
return INPUT;
}

}




Registering Validators to the ValidatorFactory

There are two ways to register Validators. This may either be done programmatically, using the registerValidator(String name, Class clazz) static method of the ValidatorFactory, or by putting a file name validators.xml in the root of the classpath with a structure like this:



<validators>
<validator name="required"
class="com.opensymphony.xwork.validator.validators.RequiredFieldValidator"/>
<validator name="requiredstring"
class="com.opensymphony.xwork.validator.validators.RequiredStringValidator"/>
<validator name="int"
class="com.opensymphony.xwork.validator.validators.IntRangeFieldValidator"/>
<validator name="date"
class="com.opensymphony.xwork.validator.validators.DateRangeFieldValidator"/>
<validator name="expression"
class="com.opensymphony.xwork.validator.validators.ExpressionValidator"/>
<validator name="email"
class="com.opensymphony.xwork.validator.validators.EmailValidator"/>
<validator name="url"
class="com.opensymphony.xwork.validator.validators.URLValidator"/>

<!--This is my custom validator-->
<validator name="duns"
class="com.ingenium.xwork_validation.validator.DUNSValidator"/>

</validators>




Notice that a custom validator has been added. But in order to use it, The ValidationInterceptor has to be turned on within the xwork.xml file like this:



<interceptors>
<!--your other validators are here-->
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
</interceptors>




Building a custom validator

A useful enterprise web application must be able to validate user inputs at UI level. Some data requires custom algorithms before it has to be committed to the database such as credit card numbers, billing account numbers, bank account numbers etc. In this topic the sample custom validator will be validating a DUNS number which stands for Dun and Bradstreet Universal Numbering System. Our code will consist of the interface which defines the operations to perform the validation, the implementation where the actual validation is performed and the accessor class where the implementation is called.

Code for IDUNSValidator.java





package com.ingenium.xwork_validation.validator;

/**
* Description: Description: This interface defines the functionalities of a
* D-U-N-S (Dun and Bradstreet algorithm) validation.
*
* @author Jared Odulio
*
*/
public interface IDunsValidator {


public static final int MODULUS = 10;

//~ Methods
/**
* Check if the D-U-N-S entry is valide
*
* @param dunsCode the D-U-N-S code to validate.
*
* @return
*/
public boolean isValid(String dunsCode);

/**
* Disposed the intance of the implementation of this interface.
*
*/
public void dispose();

}




Code listing for the DUNSValidatorImpl.java





package com.ingenium.xwork_validation.validator.impl;

import com.ingenium.xwork_validation.validator.IDunsValidator;

/**
* Description: The implementation class of IDunsValidator interface.
*
* @author Jared Odulio
*
*/
public final class DUNSValidatorImpl implements IDunsValidator {

private static DUNSValidatorImpl dunsImpl = null;
private String dunsCode = null;

/**
* Gets the runtime reference of this class.
*
* @return the created instance.
*/
public static DUNSValidatorImpl getInstance(){

if (dunsImpl == null){
dunsImpl = new DUNSValidatorImpl();
}

return dunsImpl;
}
/* (non-Javadoc)
* @see com.ingenium.xwork_validation.validator.IDunsValidator#isValid(java.lang.String)
*/
public boolean isValid(String dunsCode) {
// TODO Auto-generated method stub
this.dunsCode = dunsCode;

boolean valid = computeDunsCode();

return valid;
}

/**
* Computes the sequence of DUNS digits if it is valid.
*
* @return true if valid, false if otherwise.
*/
private boolean computeDunsCode(){

String[] sequence = new String[9];
int[] digits = new int[9];
int totalDigits = 0;
int computedDigits = 0;

//check first if the number of digits is right.
if (dunsCode.length() != 9){
return false;
}

for (int i = 0;i < sequence.length; ++i){

if (i < sequence.length - 1){
sequence[i] = dunsCode.substring(i, i + 1);
}else{
//get the last digit without end index
sequence[i] = dunsCode.substring(i);
}

//checks if entry are all numeric
try{
digits[i] = Integer.p**censored**Int(sequence[i]);
}catch (NumberFormatException nfe){
return false;
}

//checks if position is even
switch (i){
case 1:

if (digits[i] > 9){
digits[i] = computeMod(digits[i]);
}

break;

case 3:

if (digits[i] > 9){
digits[i] = computeMod(digits[i]);
}

break;

case 5:

if (digits[i] > 9){
digits[i] = computeMod(digits[i]);
}

break;

case 7:

if (digits[i] > 9){
digits[i] = computeMod(digits[i]);
}

break;
}//end of switch

}//end of for-loop

for (int i = 0;i < digits.length - 1; ++i){
totalDigits = totalDigits + digits[i];
}

computedDigits = totalDigits / IDunsValidator.MODULUS;
computedDigits = (computedDigits * IDunsValidator.MODULUS) +
IDunsValidator.MODULUS - totalDigits;

if (computedDigits == digits[8]){

return true;

}

return false;
}

/**
* Computes the modulus from the given digit.
*
* @param digits the given digit
*
* @return the computed modulus.
*/
private int computeMod(int digits){

int mod = digits;

mod = (mod / IDunsValidator.MODULUS) +
(mod % IDunsValidator.MODULUS);

return mod;
}

/* (non-Javadoc)
* @see com.ingenium.xwork_validation.validator.IDunsValidator#dispose()
*/
public void dispose() {

if (dunsImpl != null){
dunsImpl = null;
}

}
}




Code listing for the DUNSValidator.java



package com.ingenium.xwork_validation.validator;

import com.ingenium.xwork_validation.validator.impl.DUNSValidatorImpl;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.validator.ValidationException;
import com.opensymphony.xwork.validator.validators.FieldValidatorSupport;

/**
* Description: Validates entry for the Dun and Bradstreet Universal
* Number System (DUNS).
*
* @author Jared Odulio
*
*/
public class DUNSValidator extends FieldValidatorSupport {

private IDunsValidator dunsValidator = null;

/* (non-Javadoc)
* @see com.opensymphony.xwork.validator.Validator#validate(java.lang.Object)
*/
public void validate(Action object) throws ValidationException {

String fieldname = getFieldName();
Object value = this.getFieldValue(fieldname, object);
dunsValidator = (IDunsValidator)DUNSValidatorImpl.getInstance();

if (value == null){
return;
}

if (!(value instanceof String) &&
!dunsValidator.isValid((String) value)){
addFieldError(fieldname, object);

}



}



}

13 May 2005

The Hell with JES

WTF! Forgive me, 'coz I have been surrounded by stupid products these days so my rants will do no good to the proprietary sector. What happened to the good old programming and software development days?!? How come some shitty product rolls out one after another? Did the great code writers moved to another career already? I know America has been retiring their good old coders and is outsourcing some stupid ones. So I think I am starting to feel the consequence. Maybe it's not the development thing, maybe its how the products are packaged and marketed. Like this thing called JES(WTF!) aka Java Enterprise System. Basically JES consists of an application server, clustering products, Message Queue, etc. etc. Fat chance is, you'll be able to use them all. There will be, probably, one or two useful products in there and the rest are just money-wasting pile of rubbish. Another thing is the really confusing pricing scheme and a product datashit.

Inversion of Control is 2004 Buzzword of the Year

Before the official closing of the Avalon Project, many has been checking its temperature on how long it can steam out some heat, apparently it has become too soon as Spring, PicoContainer and XWork's component-based "Aware" interfaces came into high view.

But do you know any commercial product that is using Avalon until now? Let me guess, and we might say it in chorus...Yes, Weblogic 8.1. And here are some of the comments the Weblogic fans out there might say:

1. Avalon isn't that bad - Well, if it's good then it's still up.

2. You don't understand things! - This is my favorite. People that will say things like this are self-declared geniuses that write codes based on a Netbeans-generated code stubs.

3. I can't believe I am reading this - Most likely, these types has shelled out lots of money on Weblogic and currently fixing things or bracing themselves what Weblogic is cooking up that will really fuck up their applications.

4. I don't care - Most likely, these types has shelled out taxpayers' money to fix things. But when Economic Crisis rears its ugly head, it will become "Why didn't I think of this before?"

Too bad most decision makers are surrounded by witches and jesters dressed in corporate attires preaching commercial bundled software packages(particularly, American made) in the name of "accountability" and feeding themselves on such ignorance.


Good thing is, Spring is creeping its way here in Singapore, eventually Mule will make a crushing thunder in the shorelines(because this year's buzzword is SOA). AND! Even if I am really itching I still want to hold the urge to scratch, is the Space-Oriented or Space-Based Architecture. It's not yet widely "Googleable". But if Sun will really give up JCP to be an open expert group and out of vendor's interests and internal politics. Jini/JavaSpaces will flourish faster, JDO will render EJB a thing of the stupid past. And J2EE? What for? When you have spaces?

07 May 2005

Top 10 Reasons To Use NetBeans...So what?!

I just like to reinforce Mig's Post on the switching to Netbeans from an ex-user standpoint. And I found that the Top 10 reasons to switch is the same as the top 10 reasons not to switch :))


1. First To Support Java 5.0 - So what? After that, then what? What is the impact it will make to my productivity? In few days other IDEs will have the same thing as well so what's the wisdom of this being on top of the list? Ask your seatmates now, did they switched their apps to Java 5.0 that has been running for years now? Did your customer EVEN SWITCHED to 1.4 already??? This is so vague.

2. Mobility Pack - So whhaaat??!! Nokia has it's mobility SDK, Sony Ericsson does, Siemens, Motorola does and so forth and so forth. Will the Netbeans mobility pack address every manufacturer's concerns? Good Luck!


3. Project Based on Ant - SO WHAT? Will you switch from Eclipse for this reason?

4. The Profiler - There's only one Profiler tool that I believe in, it's the US$2000 Sitraka JProbe. I don't even use any Eclipse Profiling plugins. Most likely they will do interesting things on your system.

5. J2EE Development - Tell me about it. Is J2EE a rocket science? So what's the big deal about this?

6. It's fast - It's not your mother's NetBeans but it's still your NetBeans. These assholes are insulting my intelligence. I know Netbeans wasn't written by marketing people. Being a developer we all know that FAST IS RELATIVE. Now, how fast?

7. Best out of box experience - "Best" is objective. I don't know what's going on inside the Netbeans development community but it seems they enjoy tugging each other unmentionables.

8. It's Cool - Yeah and you're crazy...dorkhead.

9. More International Language Support - Netbeans developer: "...yeah because back then we thought English will be just fine."

10. 100% Java, Product of the Year - Good. Can I make money now? I am still wondering how many asses these guys kissed to get that.


Ok, yadda, yadda, yadda, yadda. I tell you what, after 4 releases they still don't have auto-imports! Organize imports! As simple as that and yet they can't still do a lot of things, I tried to use the latest release hoping I could switched back, but really it's a big turn off.

05 May 2005

Spring XDoclet

I have been hand-coding the Spring's XML application context file or known as the bean definition for quite some time. Because I am too lazy to read thru the XDoclet documentation and due to the lack of examples, especially in the @spring.bean tag section. And due to "programmer's itch" I started to tinker with it this very night. And this is what I got.

Listing 1: is a very plain sample Interface



public interface MySampleService {


public void showSpring(String greetings);

}




Listing 2: I added a simple xdoclet tag defining the bean id for Spring application context in one of the implementation classes


/**
* @author Jared Odulio
* @spring.bean
* id="sample-service"
*
*/
public class MySampleServiceImpl implements MySampleService {



public void showSpring(String greetings) {
// TODO Auto-generated method stub
if (greetings == null){
System.out.println("My Sample Service");
}else{
System.out.println(greetings);
}
}

}




Listing 3: Another sample implementation class


/**
* @author Jared Odulio
* @spring.bean
* id="another-sample"
*
*/
public class AnotherService implements MySampleService {


public void showSpring(String greetings) {
// TODO Auto-generated method stub
if (greetings == null){
System.out.println("Another Sample Service");
}else{
System.out.println(greetings);
}
}

}




Listing 3: This is our Ant build.xml file



<project name="sample-proj" default="spring" basedir=".">

<property name="conf.dir" value="${basedir}${file.separator}conf"/>
<property name="src.dir" value="${basedir}${file.separator}src"/>
<taskdef name="springdoclet" classname="xdoclet.modules.spring.SpringDocletTask"/>
<taskdef name="doclet" classname="xdoclet.DocletTask"/>
<target name="spring">
<springdoclet destdir="${conf.dir}">
<fileset dir="${src.dir}"/>
<springxml destinationfile="appcontext.xml"/>
</springdoclet>

</target>

</project>



Listing 4: When we run Ant, this what we should have


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans
default-autowire="no"
default-lazy-init="false"
default-dependency-check="none"
>

<bean
id="another-sample"
class="AnotherService"
>

</bean>

<bean
id="sample-service"
class="MySampleServiceImpl"
>

</bean>

<!--
To include additional bean definitions for Spring in the generated
application context file, add a file to your XDoclet merge directory
called spring-beans.xml that contains the markup.
-->

</beans>



There you go! Bean definition file auto-generated by XDoclet.

Take note, under normal circumstances, the build.xml file should not look as the example on Listing 3, I used Eclipse to run this, so the necessary "path" and "pathelement" tags are not present in the build.xml file because I defined all the XDoclet-related libraries in the Ant Runtime Preferences. But those tags should be defined if the build.xml has to be run outside Eclipse. I am just too lazy to do that now. And I just came from a calorie-burning, heart-pounding squash tennis game at Kallang, I should say it's BAFTB (Better and Faster Than Badminton).

03 May 2005

FreeMind

For the past few days at least there's one Java tool that could really make sense and worth giving a positive write up. It's called FreeMind. It lives up to its name, so far it does really free up my mind from the everyday clutter and distractions. FreeMind is a Mind Mapping tool, great tool for the Totally Distracted, it helps one stay focus on a particular tasks. A good first-step tool for realizing your ideas, project roadmaps, brainstorming and many more.

So if you think you're multitasking already. Think FreeMind. It gets your ideas going.

01 May 2005

Blog Recall

I don't want to remove my blog on BEA and Eclipse, but I would like to take back some few words. Still, Velocity or Tapestry and WebWork2 are STILL the way to go. Luckily, when you're grown and cultured with some seriously good tools, it's hard to let go. Especially when people are still thanking you and new guys that replaced you praising for your job well done using those tools. It's freakingly easy to maintain.

I thought the Pollinate/Beehive thing is a coming-to-reality or accepting-the-defeat transition. This is just an insidious ploy to lock-in developers and users deeper. I want to puke. So ok I want to drill down on few things to watch out for:

Struts Sucks - it's playing a catch-up game with Webwork2 nowadays making its API obnoxiously inelegant.

BEA Weblogic Workshop Sucks - It's just a snake shedding old skin.

JBoss Sucks - bigtime

Hibernate Sucks - Double bigtime

JSP Sucks - Come on guys grow up

The Java Open Single-Sign On

I am wondering why there are still some developers out there doing single-sign on the hard way. Talking about reinventing the wheel? Looking at JOSSO or the Java Open Single-Sign On, there's much to achieve from this tool. Although I haven't tested it yet, but it should comply to the JAAS standards. And by open source standards(if you know what I mean), JOSSO is decently documented. The Reverse Proxy Support is quite promising, it allows you to create multi-tier single sign-on configurations.

BEA and Eclipse

Honestly, I hate commercial software vendors. These hatred grew not here in Singapore. For obvious reasons that back in the Philippines they are expensive and you can't make real money out of it. So the mindset has become like this: Find an open source counterpart that is equally robust and stable, develop on it, be proficient with it and consult with it. So when it comes to Java development, the weapon of choice is Eclipse, whether the project is web, stand-alone or real-time. Every project was delivered using Eclipse, it has become an indispensable tool at no cost to the developers. Another reason is the dreaded "vendor lock-in". Commercial software vendors deprive users and developers choice of tools which is dangerously costly.

Alright, Alright, I'll cut to the chase. I hate BEA Weblogic Workshop, that damn thing is a piece of limited, proprietary shit. And I am not keen on giving up my powerful Light Sabre(which is Eclipse by the way) for a rusty dagger like BEA Weblogic Workshop.

Fortunately, about a year ago and I missed this news for the reason that I am not your savvy Webby guy (I'll shoot anyone who will call me a Web Developer). BEA backs the Beehive is an evolution of the BEA Weblogic Workshop product. So meaning the old thing is a freaking history so why bother use it?

BEA has created a project for Eclipse called Pollinate to integrate Eclipse with Beehive. Open Source rules again! I think Pollinate is worth evangelizing in Singapore.

Blogging in Singapore

I found Andy Ho's article quite disturbing, being a foreigner working here.

I haven't read Mr. Chua's blogs on his "alleged disdain for the minorities" in Singapore or I didn't even know the level of anger or hatred he had for the minorities. Yes, for now we can't hang him out to dry. But the question is, what if his whole viewpoint is actually that? What does the taxpaying "minorities" feel about him being sent to U.S. to study using their money and eventually work as "public servant" to "serve" them?

Good thing he has been reprimanded. But I would suggest a remedial course for him that he'll never learn from his entire scholarship period in the U.S., I'll have him study with "hands-on" in the Philippines on how to be a public servant in one of our islands called Basilan. I'll bet he will learn hard, fast and chastened. It's worth the taxpayer's money.