Showing posts with label Technical Discussion. Show all posts
Showing posts with label Technical Discussion. Show all posts

Wednesday, January 07, 2009

The Nasty JPA "Unknown abstract schema type" error

I been trying to debug the following error for days, and it drive me nuts!

The problem: JPA refuse to compile one of my NamedQuery, and throws the following error:

Error compiling the query [UserVO.findByUserName: SELECT u FROM UserVO u WHERE u.name = :name]. Unknown abstract schema type [UserVO]

After numerous Google search, I conclude that JPA will throw "Unknown abstract schema type" when JPA fail locate your entity class". Most often, this type error occurs when:
  • Developer have put down database table name instead of Entity Class name in the JPA query. eg. if we have a EntityClass UserVO which map to table name users, the query "SELECT u from users u" will throw the above exception.
  • When running JPA in standalone, or not JavaEE container(such as Tomcat 5/6), they forgot to explicit list all entities class in the persistence.xml, thus JPA fail to locate the entities when compile the query.
None of above apply to my case, I have explicit listed all my entities class in the persistence.xml
and I am sure my JPA query is valid. I have tested my code with different JPA implementations, but always resulted the same error..

Here my UserVO class


@Entity(name = "users")
@NamedQuery(name = "UserVO.findByUserName",
query = "SELECT u FROM UserVO u WHERE u.name = :name")
public class UserVO extends implements Serializable {

|
|
}


If I remove the NamedQuery, my JPA able to work as expected, i.e I am able to insert, delete, and update UserVO object.
Now, to all my smart reader, can u spot what's wrong in my code? Scroll down for answer.


|
|
|
|
|
|
|

Answer: The culprit is the Entity annotation, I explicit name the UserVO entity as users, which JPA have no problem to map the UserVO to users database table, but have problem to compile the JPA Query, because it can't find the UserVO entity in the JPA context, as the suppose UserVO entity have rename to users entity by me, got it, or confuse..

To resolve this, just add a @Table annotation with the table name, as shown code below:


@Entity
@Table(name = "users")
@NamedQuery(name = "UserVO.findByUserName",
query = "SELECT u FROM UserVO u WHERE u.name = :name")
public class UserVO extends implements Serializable {

|
|
}


Cheers, Happy New Year!!!!

Friday, November 21, 2008

[Tips] tired of Windows Spam and Virus?

Then listen to me, please try "Ubuntu 8.10!, the right OS!"
Once u download, and install, follow this guide to make ur desktop sexy, here are some screen shots of my current desktop, very sexy and very productive..


Running on Awn launcher bar and Conky that display
weather, CPU stat, and my gmail status.


I have up to 4 virtual desktops to work with.


The sexy task switcher..


Rotate the desktop cube, just to impress Windows user.
btw, the background image is the pic I take from KL Lookout point.
if u interest, u can download the pic from http://flickr.com/photos/jameskhoo


and finally, because Ubuntu 8.10 comes with VirtualBox, u can install
Windows Vista, and surprising, it run very smooth on top of Ubuntu.

If u still not convince, do check out this Video
Haha, enjoy!

Tuesday, April 15, 2008

A quick update on JPA Boolean Magic Converter

Some update on changes:
  • Fixed the bug of Null pointer exception, when JPA return null on the annotated field.
  • Introduce a new properties call ifNull, which allows user to configure what to return if JPA returns null, it expect enum of org.jbpcc.util.jpa.ReturnType, which have values of ReturnType.True, ReturnType.FALSE, and ReturnType.Null,. The default value of ifNull is ReturnType.Null
Thus as an example, assuming we have model class define as below:

package org.jbpcc.domain.model;

import javax.persistence.Entity;
import javax.persistence.Id;
import org.jbpcc.util.jpa.BooleanMagic;
import org.jbpcc.util.jpa.BooleanMagic.ReturnType;

@Entity
public class SomeVO {
@Id
private Integer id;
@BooleanMagic(trueValue = "Yes", falseValue = "No",
columnName = "OVERDUED", ifNull = ReturnType.FALSE)
private transient Boolean overdued;

public Boolean isOverdued() {
return overdued;
}

public void setOverdued(Boolean overdued) {
this.overdued = overdued;
}
}

Java APT with JPABooleanMagicConverter factory, code above will be converted to:

@Entity
public class SomeVO {
@Id
private Integer id;
private transient Boolean overdued;
//--- Lines below are generated by JBPCC BooleanMagicConvertor PROCESSOR
//--- START :

@Column(name="OVERDUED")
private String magicBooleanOverdued;


public Boolean isOverdued() {
if (this.magicBooleanOverdued == null)
return false;
return this.magicBooleanOverdued.equals("Yes") ? Boolean.TRUE : Boolean.FALSE;
}

public Boolean getOverdued() {
if (this.magicBooleanOverdued == null)
return false;
return this.magicBooleanOverdued.equals("Yes") ? Boolean.TRUE : Boolean.FALSE;
}

public void setOverdued(Boolean trueFlag) {
this.magicBooleanOverdued = trueFlag ? "Yes" : "No";
}
//--- END
//--- GENERATED BY JBPCC BooleanMagicConvertor PROCESSOR

}


That's all, as usual, you could find the JPABooleanMagicConverter binary at http://code.google.com/p/jbpcc/downloads/list.

Do share me your thoughts and comments, happy coding

Sunday, April 13, 2008

A portable JPA Boolean Magic Converter

While doing some small POC with JPA, I am surprise to find out that the current Java Persistence API (JPA) standard does not mandate JPA provider to support data type conversion via annotation, not even a with simple boolean field. For reader who unfamiliar with JPa, what I means is, to persist and "JPA" manage a boolean field, JPA expect the database data type to be integer, where value of "1" means true, and value of "0" means false.

You got to be joking, right? Every "real life" programmer knows that, there are many existing database use different combination of char or string on a table boolean field, such as "True/False", "T/F", "Yes/No", "Y/N", "-1/0", and etc. Thus, as a "real life" programmer, I kind expect the JPA should allows me specific a boolean field via Annotation, such as example below:

@booleanField(trueValue="Yes", falseValue="No")
private Boolean enabled;

And to my surprise, the answer is nope!!!..So far only Hibernate JPA provider provide data type conversation. Daniel Pfeifer, have explain the problem in details, he also discuss some solutions to work around this stupid limitation at his blog, title "Type Conversation with JPA", do check it out.

Daniel's "manual mapping" idea, do solve the limitation. However, maybe it's just me, I just don't like the idea to temporary change a Boolean field to map with database data type (either char, string) in order to resolve the limitation, even we make the field private, this is just me. And I am stubborn, and old . :-)

Anywhere, after some research (Also, a good excuse to my manager to research how difficult to come out our own custom Java 5 annotation with custom Java APT process factory), I come out our own compile time annotation, called @BooleanMagic with our own BooleanMagicProcessorFactory, which I hope, shall temporary resolve the problem.

@BooleanMagic comprise of three attributes:
  • trueValue, specified the table boolean field true value here, such as "True", "T", "Yes"
  • falseValue, specified the table boolean field false value here, such as "False", "F","N"
  • columnName, tableColumn name;
Also please note that BooleanMagicProcessorFactory mandate any field annotated with @BooleanMagic annotation, must either annotated with @Transient annotation or with modifier transient.

Thus, as an example, assuming we have a boolean field called "enabled", which map to table "ENABLED" field, with boolean value of "True"/"false", we will specified our VO as below:

@Entity
public class SomeVO {
@Id
Integer id;
@BooleanMagic(trueValue="True", falseValue="false", columnName="ENABLED")
private transient Boolean enabled;

public Boolean isEnabled() {
return enabled;
}

public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
}

Using Java "APT" tool with JPABooleanMagicConverter factory, code above will be converted to:


@Entity
public class SomeVO {
@Id
Integer id;

private transient Boolean enabled;
//---
//--- Lines below are generated by JBPCC BooleanMagicConvertor PROCESSOR
//--- START :

@Column(name="ENABLED")
private String magicBooleanEnabled;

public Boolean isEnabled() {
return this.magicBooleanEnabled.equals("True") ? Boolean.TRUE : Boolean.FALSE;
}

public Boolean getEnabled() {
return this.magicBooleanEnabled.equals("True") ? Boolean.TRUE : Boolean.FALSE;
}

public void setEnabled(Boolean trueFlag) {
this.magicBooleanEnabled = trueFlag ? "True" : "false";
}

//--- END
//--- GENERATED BY JBPCC BooleanMagicConvertor PROCESSOR
}


Now, isn't that cool (haha, sorry, I am bit biased here). Btw, BooleanMagicConvertor is portable across JPA protable, and IMHO, this is a better interim solution till JPA make data conversation standard.

I decided to contribute my BooleanMagicConverter back to open source community, it's currently park under my open source project Java Batch Process Control Center, at http://code.google.com/p/jbpcc, you could either build from the source, or get the "BooleanMagicProcessorFactory.jar" from here.

Here an example of how to use the BooleanMagicConvertor using Ant 1.7 apt tasks, assuming all your entity class is declare at ${src.dir}/org/abc/domain/model directory, and you wants to output all generated call to ${basedir}/target directory
 <target name="preProcessJPABoolean" depends="buildJPABoolenProcessorFactory">
<apt srcdir="${src.dir}/org/abc/domain/model"
destdir="${build.classes.dir}"
classpath="./dist/BooleanMagicProcessorFactory.jar:./lib/Model_Dependent_thirdparty.jar"
debug="on"
compile="false"
factory="org.jbpcc.util.jpa.BooleanMagicProcessorFactory"
preprocessdir="${basedir}/target">
</apt>
</target>

That's all, do share me your thoughts and comments, cheers!

Thursday, March 27, 2008

I started yet another open source project



I decided to start another open source project name Java Batch Process Control Center (JBPCC). "What, another open source project again!, what happen to your suduko project?", some of u may ask. Well, the project still hosted at sourceforge, we just not going to maintain the project any more. Reason being, I am tired of suduko already, and there are far too many variance of suduko open source project exists. Sorry!

Anywhere, the idea of Java Batch Process Control Center is somehow continue from my original idea on "Automatic Remote Logging Management via JMX". by using Java 5 instrument API, developer able to "wrap" any Java base process, and automatically offer JMX monitoring and remote logging management functionalities, and the idea of JBPCC, is to deliver end user an AJAX web application to manage, monitor and schedule any those "wrap" processes.

Proposed Features:
  • An in-memory module for remote servers to register, execute, and manage batch processes.
  • Time-based and duration-based scheduling of any configured or registered batch process for execution.
  • Monitoring currently running processes, including resources used and logs.
  • Server management for configuration of servers that hold remote batch processes.
  • A simple rights-based user management module.

Our project is hosted at http://code.google.com/p/jbpcc , Please note that, as this is still a fairly new project, there isn't much user could download from our project repository. But, rest assure that, we will post project news, progress report, tutorial, even web cast here. So, stay tune..

Wish me luck!

Friday, December 14, 2007

Glass Fish Installation from Hell, really?

I like Sun's open source application server, GlassFish, thus when I feels a bit offended when Jevgeni Kabanov wrote an article about how difficult to install GlassFish, and comments that the documentation is suck, and not friendly..

Hm, ok, to give Jevgeni Kabanov benefits of doubts, I decided to do a fresh installation of GlassFish version 2, and observe the manual installation process myself..maybe he is right, as my GlassFish always pre-bundle with Netbeans, and so far, I haven't try to install GlassFish maually myself.


So.here it go..
a) I visit GlassFish's web site at https://glassfish.dev.java.net/

b) I click on "download GlassFish v2 now" icon, and directed to this page https://glassfish.dev.java.net/downloads/v2-b58g.html
, which I presented a step by step instruction on how to install GlassFish, follows by links to download GlassFish binary for various platform

c) I choose to download GlassFish build for Linux platform, as I am running on Ubuntu Gusty. Once download, I follows the documented instruction to install GlassFish, i.e
-> java -Xmx256m -jar "downloaded.jar"
-> cd glassfish
-> chmod -R +x lib/ant/bin
-> lib/ant/bin/ant -f setup.xml

d) Once setup, I follows the quick start guide to start the application server, i.e.
->Add the install-dir/bin directory as PATH env variable
-> Start the server "asadmin start-domain domain1"

e) To verify, I open my browser, and points the URL to http://localhost:8080, which I presented a welcome page, and messages stated my server is up and running running..BTW, port 8080 is default installation port, and u could change the default port by editing the setup.xml

f) To manage the server, I point my browser at http://localhost:4848 to access GlassFish admin console, I entered my given admin user id and password (ie admin, password, adminadmin) to login to the console. I presented a very nice GUI to manage my server, and deploy my application (WAR, EAR, and etc).

g) To deploy one of my application, I click "Deploy web application(.war)", select my war file, and click deploy, and just like that, my application is up and running..

That's it, the whole process takes less then 20 minutes (depends on how fast ur internet connection is to download the installation jar), and all the steps above are well documented at GlassFish's installation and quick start guide. I admit the installation process is "out of norm" and could be improve, but to go to the extends and claim it is installation from hell is bit too extreme, isn't?

Peace!

Monday, November 05, 2007

Automatic Remote Logging Management via JMX.

Wow, the post title definitely sound “very technical”, and I do hope that it will attract more readers here. :-)

It all started a weeks ago, where I have accidentally discovered a “hidden JDK 5 treasure” (from Daniel Fuch, blogs http://blogs.sun.com/jmxetc/) , called java.lang.instrument, a Java package that provides services that allowing Java language agents to instrument programs running on the JVM. Most people use it for profiling, or pre-instrument purpose.


But I have a idea, why don't we create a logging management wrapper, which allows us to wrap any Java application, and provide us some logging management functionalities without any modification on our application source code. The logging agent will offer the following:

  • Abilities to change log level (debug, info, warning, error) on any configured logger dynamically without restart.
  • Abilities to locate any configured log output files.
  • Abilities to browse (either head, or tail) any configured log files.
Base on requirements above, I come out JMXMBean interface below:


public interface RemoteLoggingMBean {
  public void activateDebug(String loggerName);
public void activateInfo(String loggerName);
public void activateWarning(String loggerName);
public void activateError(String loggerName);
/**
* Retrieve current configured log output files base on given logger.
* The system will only return log files with the following appender
* org.apache.log4j.DailyRollingFileAppender, org.apache.log4j.FileAppender
* org.apache.log4j.RollingFileAppender;
* @param loggerName
* @return Array of file name with relataive file path points to current running directory.
*/
public String[] retrieveCurrentConfiguredLogFiles(String loggerName);
/**
* Similar to Unix head command, read a text file forward from the beggining
* of the file till it reaches line limit, or EOF
* @param fileName the logFileName.
* @param linesToRead, Number of line to be read.
* @return JMX CompositeData with the structure of StartFilePointer (SimpleType.Long),
* EndFilePointer(SimpleType.Long), LogMessages(SimpleType.String)
* @throws java.io.IOException
*/
public CompositeData headLog(String fileName, int linesToRead) throws OpenDataException, IOException;
public CompositeData headLog(String fileName, int linesToRead, long fromFilePointer) throws OpenDataException, IOException;
public CompositeData tailLog(String fileName, int linesToRead) throws OpenDataException, IOException;
public CompositeData tailLog(String fileName, int linesToRead, long fromFilePointer) throws OpenDataException, IOException;
}

The rest of code is delivered by using various JMX and Apache Log 4J API, which I am not going to discuss here, as this is obviously not JMX nor Java Logging tutorial.

If u interest, u could download the whole project source from here. Is not under any copy write protection. U are welcome to download it, modify it, change the author name, use it or distribute it to anyone. IMHO, The IT have to many unfair patents, or copy protection law, which in a way, have stop us on moving forward.

Anywhere, back to topic. To use the wrapper on any Java application that use Apache Log4J for logging, follows steps below:

  1. Either download the binary RemoteJMXLoggingAgent.jar, or build it from the source
  2. Put the binary to your application class path, make sure it sit together with log4j.jar
  3. Append the line at your Java Application startup script
"-javaagent:(deploy directory)/RemoteJMXLoggingAgent.jar
-Drmi.agent.port=AnyRMIPort (optional, default=3000)"


That's it, u application is now able to offer above Remote Logging management functionalities via JMX. To test this, open jconsole from any PC, and connect your remote application via the JMX URL below:
service:jmx:rmi:///jndi/rmi://hostname:rmi_port/remoteLoggerAgent

The Mbean on managing your application logger is called "org.coolboy.RemoteLoggingManager", have fun!


Tuesday, October 23, 2007

Before upgrade to Windows Vista..

Seriously, think twice before u upgrade, o consider open, secure and free alternative Linux OS. Out of so many Linux distribution, I strongly recommends Ubuntu Gusty.
Here why:
  • Needs goods reasons why Linux is better OS compare with Windows> looks here.
  • It just work - Upon installed, ubuntu detected my all my devices, and install drivers correctly, this include my media card, wireless network, video, usb, and etc.
  • Dell start selling PC/notebook with Ubuntu pre-installed, other vendor like Lenovo will follows soon.
  • If u impressed Windows Vista offer "Wowo wow"3D desktop effect, well, looks what Ubuntu Gusty + Compiz offer:


  • Linux could run Windows applications such as MS Outlook, PhotoShop, IE, even MSOffice (If u really really have to, but do consider use open office..) either via Wine (A windows emulator), or via Windows XP vmware image. User could create an empty OS image using VMware server (Free), and install Windows XP (Using legal Windows XP licenses, off course), and install applications on the vm image created.


Seriously, do u really have to upgrade to Windows Vista, post your doubts on my comments page, I am more happy to help here

Monday, May 21, 2007

100% Unit Test Code coverage using Mock, does it really matter?

I always believe delivering a comprehensive integration/functional testing code is far far more important/productive than blindly try to achieve 100% unit testing code coverage. I believe:
a) A integration/functional testing code will always deliver more test coverage then unit testing code.
b) Integration testing code allows us to capture our program error as earlier as possible, and avoid “big bang” integration error at the end.

Thus, I always have “heat and interesting” discussion with some developers where they always believe:
a) Achieve high percentage of unit testing code coverage is very important
b) unit testing code must be “unit testable”, all dependency classes/resources should be “mocked”, even sometime is so so difficult to mock such objects.
c) if our code is not testable, that must be something wrong with our design. We have to change our code to make it testable. Thus making our class final, or our class not implementing an interface, or using static methods are all bad!.

Don't get me wrong, I am not 100% against points above, and I understand important of unit testing. But believe the unit testing code we deliver must return good “Return of Investment” (ROI). Investment here mean our effort of delivering/maintaining the unit testing code. A good ROI unit testing code have the following characteristic:
a) It use “black box” approach , where we pass parameters to a method, test the method and we verified the return value against expected result, we should not care how's the methods executed, and what underlying resources being called.
b) The testing code should be easily promoted to functional/integration testing code, why reinvent the wheel?
c) The testing code must drafted base on agree use case, and tight back to your application's features. Thus, using HR application as an example, to unit test you annual leave application is always approved by your manager produce good ROI value. but to unit test your database connection pooling utilities, or utilities to read properties files or parsing a fake XML file does not produce good ROI value.

To illustrate what I mean by good ROI unit testing code, consider the following examples:


Public class OrderManager {
public boolean proceedOrder(OrderVO anOrder) {
return ( inventoryManager.hasStock(anOrder) &&
accountManager.customerGoodCreadit(anOrder.getCustomer()) &&
shipmentManager.shipmentDateOK(anOder.getPreferShipmentDate()
);

}


To unit test proceedOrder() methods using Mock:

1. First, create InventoryManager, accountManager, and shipmentManager mocks

2. Instruct our mock framework on mock methods that called, and for each mock methods call, we instruct expected return value.
3. And finally, we test return value with our expected result, and ensure mock methods being called.

Does the above code give us good ROI? IMHO, it does not...

a) It's breaking the black box testing approach, we are telling our mock framework steps by steps what mock methods will be call, and specifically ask them to return the value we set, and test method proceedOrder() return value with our expected result, which we already know what it will return in the first hand.

What happen if we wants to change the implementation, do we have to change our testing code as well.

b) It does not bring any business value...

A ROI testing code for the above use case:
1. Set a InventoryManager product (say product “A”) quantities to a specific amount (say 50)

2. test the proceedOrder() by placing product A with various quantities
3. Verify the result against expectedResult

So, to conclude, if a unit testing code does not produce good ROI, do spend more time on delivering functional/integration testing code, and delivering good "ROI" usable code coverage

Apply my points to Automobile industries, we will not hear an engineer that create mock of car tires, or create a mock for road surface to test a car braking system, he/she will actually “integrate” the braking system with a set of tires (make by different rubbers), and conduct braking test on various surface (maybe on a rolling board with different surfaces)

Share me your thoughts...

Tuesday, February 27, 2007

[quick tips] To Speedup your junit testing in Ant

If your development project get bigger, and have incorporated thousands of test cases, u may find that unit testing target getting slower and slower. It may come to a point your developers start to ignore test cases, or worst, don't write any test cases at all, as it will slow down build process.

Now, before u look into your unit testing code to improve the performance, why don't have a check on your Ant Junit Target (I discovered this accidentally yesterday, as I am frustrated by the slow build process). If u have setup ur Ant to fork a new JVM for unit testing target, by default, Ant will fork a new VM per Test Class, which is slow, and expansive (imagine forking 1000+ jvm for your project). To correct this, we just needs to set correct forkmode="perBatch".
i.e
junit fork="true" forkmode="perBatch"

My test result, before forkmode="perBatch", my test process take ~= 16 minutes
after, my test process take < 2 minutes

Cheers, and happy coding

Monday, February 12, 2007

[Tech Tips] Implementing Command Design Pattern via Spring Framework - Part II



The RemoteControl class needs to hold list of supported commands, and needs to delegate request to respective command class base on the pass in command string. Here is the RemoteControl source:

 1
2 package blog.coolboy.springexample.cp;
3
4 import java.util.List;
5 import java.util.HashMap;
6 import blog.coolboy.springexample.cp.command.CommandType;
7 import blog.coolboy.springexample.cp.command.Command;
8
9
10 public class RemoteControl {
11
12 private HashMap<String, Command> supportedCommands = null;
13
14 public RemoteControl() { }
15
16
17 public void setListOfSupportedCommands(List<Command> commandList) {
18 supportedCommands = new HashMap<String, Command>();
19 for(Command cmd : commandList) {
20 supportedCommands.put(
cmd
.getCommandType().getCommandString(),
cmd
);
21 }
22
23 }
24
25 public void execute(String cmdString) {
26 Command cmd = supportedCommands.get(cmdString);
27 if(cmd != null) {
28 cmd.execute();
29 } else {
30 System.out.println("The cmd->" +
cmdString
+ " is not supported!");
31 }
32 }
33
34 }
The RemoteControl will transfer a list of supported commands to internal HashMap using commandString as object key, thus, removing the needs of iterating commands list for each new command execution.

Here's the fun part, we will inject list of supported commands to the RemoteControl above using Spring XML configuration, as shown in code below:

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

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
>

<!-- listing of supported Commands here -->

<bean id="tvOnCommand"
class="blog.coolboy.springexample.cp.command.impl.TVOnCommand"/>
<bean id="tvOffCommand"
class
="blog.coolboy.springexample.cp.command.impl.TVOffCommand"/>
<bean id="lightOnCommand"
class="blog.coolboy.springexample.cp.command.impl.LightOnCommand"/>
<bean id="lightOffCommand"
class="blog.coolboy.springexample.cp.command.impl.LightOffCommand"/>

<bean id="remoteControl"
class
="blog.coolboy.springexample.cp.RemoteControl">
<property name="listOfSupportedCommands">
<list>
<ref bean="tvOnCommand"/>
<ref bean="tvOffCommand"/>
<ref bean="lightOnCommand"/>
<ref bean="lightOffCommand"/>
</list>
</property>
</bean>
</beans>


That's all, our remote control class is finished. To roll out new Command, developer just needs to
1. declare the new command type, and it's command string at the CommandType enum
2. implements the command, and
3. inject new command via Spring Configuration.


Here are remoteControlService class to test the remoteControl

 1 package blog.coolboy.springexample.cp;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import org.springframework.context.support.ClassPathXmlApplicationContext;
7 import org.springframework.context.ApplicationContext;
8 import org.springframework.jms.listener.DefaultMessageListenerContainer;
9
10 public class RemoteControlService {
11 public static void main(String [] args) {
12 ApplicationContext context =
new
ClassPathXmlApplicationContext("/conf/remoteControlConfig.xml");
13 RemoteControl remoteControl = (RemoteControl) context.getBean("remoteControl");
14 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
15 System.out.println("Remote Control Ready, enter 'Quit' to terminate the program");
16 String txtCommand;
17 try {
18 do {
19 System.out.print("Enter your command->");
20 txtCommand = reader.readLine();
21 if(txtCommand.equalsIgnoreCase("quit")) {
22 break;
23 } else {
24 remoteControl.execute(txtCommand);
25 }
26 System.out.println("");
27 } while(true);
28 } catch (IOException ex) {
29 ex.printStackTrace();
30 }
31
32 }
33 }
Here are the try run:
------------------

Remote Control Ready, enter 'Quit' to terminate the program
Enter your command->tv.on
Switching On TV
Enter your command->tv.off
Switching off TV
Enter your command->light.on
Turning on Light
Enter your command->light.off
Turning off Light
Enter your command->quit

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

Isn't this fun? In the next article, I will explain how I would extends the app to support JMS and SOAP command request, using Spring, stay tune.

Friday, February 09, 2007

[Tech Tips] Implementing Command Design Pattern via Spring Framework - Part 1


I been using Spring Framework for pass few months, and I am big fans of the Framework. The framework help a lot, as we don't have to write lengthly, repetitive boring code, most application code are wire via Spring XML configuration, the framework also make our code cleaner, as it provide out of box AOP engine, developer could focus on implementing module core function, and “AOPing” other programming aspects such as transaction control, logging, security, and etc when require.

Thus, to say a big thank u on providing such great framework, and contribute back to the communities, starting from today, I will use this blog to share my experience, tips, and journal of using Spring here. Most of the write up will assume u have some basic idea of using Spring (Just do a google search on Spring tutorial).

So, my very first 2007 technical topic is “Implementing Command Design Pattern using Spring”. I will use the remote control example from very popular design pattern book, “Head First Design Patterns” from OREILLY.

The original requirement of the remote control are

1 . The remote control will have multiple buttons,
2. Each button could be program to turn on/off a household device.

I change the requirement a little, the remote control will not have any buttons, but:

1. It will accept command as a string from a console
2. Each device's command will have unique command String, such as

The very first thing we need to do is to roll out the command interface


1 package blog.coolboy.springexample.cp.command;
2
3 public interface Command {
4 public CommandType getCommandType();
5 public void execute();
6 }


Next, we needs to define an enum to hold all possible supported CommandType, each CommandType holds it's command string, which is unique. That's a helper method to return CommandType base on passing command string.
 1 package blog.coolboy.springexample.cp.command;
2
3 public enum CommandType {
4 LIGHT_ON("light.on"),
5 LIGHT_OFF("light.off"),
6 TV_ON("tv.on"),
7 TV_OFF("tv.off");
8
9 private String commandString;
10
11 // return CommandType base on passing
12 // commandString
13 public static CommandType valueOfCommandString(String cmdString) {
14 CommandType theCommandType = null;
15 for(CommandType cmdType : CommandType.values()) {
16 if (cmdType.getCommandString().equals(cmdString)) {
17 theCommandType = cmdType;
18 break;
19 }
20
21 }
22 return theCommandType;
23 }
24
25 CommandType(String cmdString) {
26 commandString = cmdString;
27 }
28
29 public String getCommandString() {
30 return commandString;
31 }
32
33 public void setCommandString(String commandString) {
34 this.commandString = commandString;
35 }
36
37 }
38

Now, implements all supported commands, below is sample code TV ON Command;

 1 package blog.coolboy.springexample.cp.command.impl;
2
3 import blog.coolboy.springexample.cp.command.Command;
4 import blog.coolboy.springexample.cp.command.CommandType;
5
6
7 public class TVOnCommand implements Command {
8
9 private final static CommandType cmdType = CommandType.TV_ON;
10
11 public TVOnCommand() {
12 // U suppose to pass in a TV instance here..
13 }
14
15 public CommandType getCommandType() {
16 return this.cmdType;
17 }
18
19 public void execute() {
20 System.out.println("Switching On TV");
21 }
22
23 }

The rest of commands (TV.Off, Light On, Light.Off) follows the same structure..

In part II, we will roll out the RemoteControl class, and use Spring to inject supported commands to the Remotecontrol, and provide remoteControlService as an interactive shell for user to test out the remote control, stay tune.

Wednesday, March 22, 2006

Project All About Sudoku!

"Hi I am James, and I am addicted to Sudoku, it all started few weeks ago...".

I admit that I am very addicted to the game. I must play at least one Sudoku puzzle a day or else I feel that something is missing from me. And it's a very good brain exercise for everyone, is highly recommended for anyone who's older then 30+ and people will start calling u "uncle", like me :-(

I love the game so much that I was actually thinking of putting one Sudoku puzzle as part of the interview questions for a Java developer position which I'm hiring for my present Company. I think that if one can't even solve a simple Sudoku puzzle within a given time frame, their problem solving skill is pretty much limited. Somehow, my Manager rejected this idea.

My "Geek" friend Paul Ho and I had several interesting discussions about the game ... about algorithms on generating a unique Sudoku, what is the best program logic to solve a given puzzle ... so on. As a 120% "geek" than me and a very good Java developer, Paul was able to come out with a Java base Sudoku game under 4K and completed within 1 week time frame. Well done Paul! Bravo !

Paul 4K Sudoku game (download from here) actually triggered me to start my very first open source project called "Project all about Sudoku" hosted at sourceforge.com. The aim of this project is to provide a platform (A Java Swing Application) for developers around the world to participate by delivering various kind of plugins to make this addictive game more fun, entertaining and most importantly ... Free For All!.

Well, this project just went "live" yesterday and u can download a "SQLPlus" version of the game. Appreciate if u could check it out and do tell me what do u think. I could use all your support to boost the project ranking.

Thursday, September 22, 2005

[Tips ] – “On the fly” deployment under NetBeans

Here's my problem, I have three set of application configuration files (e.g. project properties, hibernate configuration, log4j properties, and others) setup for three different deployment environments, there are:
-1. Production, my application will be connected to client's Oracle database, and log level set to warning.
-2. Local, HSQLDB running on my local machine will be use, log level set to debug
-3. Test, for unit testing purpose

I am a lazy person, I wants my build script to prompt me which mode I would like to deploy, prior it compile, package and deploy my application. Listed below are the steps to how I achieve that:
- Firstly, I create a folder name "cfg" under project project, I then create “production”, “local”, and “test” folders under the cfg folder.
- Put properties files in to respective folder, shown in figure below:


- Open build.xml and add in new target, called “-pre-compile”, which will prompt user deployment mode, and copy respective properties to src directory prior any compilation, as shown in code below:


    <target name="-pre-compile">
            <input message="Please enter deploy mode? (production, local, test)->"
                    addproperty="mode"
                    defaultvalue="local"/>
            <echo message="Copying application configuration file for ${mode} mode"/>
            <copy todir="${src.dir}" overwrite="true">
                <fileset dir="${basedir}/cfg/${mode}"/>
            </copy>
    </target>

- Clean and Build my project, surprise, surprise, Netbean actually popup a nice dialog ask me to enter deploy mode, as shown in figure below:




- That's very nice, but I am lazy person, remember. I don't want to type "production", "local", or "test" each time I want to deploy my application. So, I modified ant script a little bit by inserting a validargs element at the input taks, as show in code below:

    <target name="-pre-compile">
            <input message="Please enter deploy mode? (production, local, test)->"
                    validargs="local,production,test"
                    addproperty="mode"
                    defaultvalue="local"/>
            <echo message="Copying application configuration file for ${mode} mode"/>
            <copy todir="${src.dir}" overwrite="true">
                <fileset dir="${basedir}/cfg/${mode}"/>
            </copy>
    </target>

- Clean and Build my project, Netbean surprise me again, by showing me a popup with a pulldown showing available delopyment modes.



Now, that what I called hidden Easter egg in Netbean..Enjoy!



[Tips] Wanted to use Log4j with Sun Java System App Server 8?

I prefer log4j over JDK 1.4 logging library, hera are some of the "obvious" reasons: How about log4j comes with more appenders compare to JDK1.4 Logging, it easier to configure, and support many layouts. However, log4j does not “sits” very well in our App Server, some of identified problems are:
1.Deployed logging configuration file (i.e. log4j.properties) is totally ignore, even we put in correct class path.
2.Logger ClassCast Exception upon restart of an application server instance.

A further investigate reveal that our Apps Server use JDK1.4 logging (i.e. Java.util.logging) via apache commons-logging, which should be avoided according to this article http://www.qos.ch/logging/thinkAgain.jsp, I agree. So, here's propose “work around”:
1.Write you own log4j wrapper class. Refer to “Ch9, Log4j, the complete manual” by log4j author Ceki Gülcü for more information on how to write a good log4j logger wrapper class.

2.Create a new Logger Manager, which will a)Configure log4j properties if is not configured yet b)Return the logger wrapper class to calling class. As an example of such Logger Manager class:
   1:
2:public class MyLogManager {
3: private static boolean isLogPropertiesConfigure = false;
4:
5:
6: public MyLogManager() {
7: }
8:
9:
10: public static MyLog4JWrapper getInstance(String logInstance) {
11: try {
12: if (!isLogPropertiesConfigure) {
13: PropertiesConfiguration pp = new PropertiesConfiguration(Constants.PRJ_PROPERTIES_FILE);
14: String configFile = pp.getString(
15: "log4j.properties.file");
16: FileInputStream istream = new FileInputStream(configFile);
17:
18: Properties props = new Properties();
19: props.load(istream);
20: istream.close();
21: PropertyConfigurator.configure(props);
22: isLogPropertiesConfigure = true;
23: }
24: } catch (Exception e) {
25: System.out.println("Error :" + e.toString());
26: }
27:
28: return new MyLog4JWrapper(logInstance);
29: }
30:}
3. Finally, use LoggerManager, and MyLogJWrapper for logging in your J2EE applications, example:
   1:public class MyClass{
2: static MyLog4jWrapper log= MyLoggerManager.get(MyClass.class.getName());
3:
4:
5:
6: public void someMethod() {
7: log.debug("Testing...");
8: }
9:}