blog moved to blog.aujava.com

April 24, 2007

Recently I have moved the blog to better place :)  Please update your bookmarks.  blog.aujava.com

Generic OGNL Controller without Spring WebFlow

January 22, 2007

While working on various web projects many times I felt guilty for writing controllers that perform one-two rows of the code.
It must be easier way! And when I read and tried Spring WebFlow I really liked their approach for defining how to call methods on any exposed bean.
It is what I was looking for. Simple things made easy inside the xml config:

 <bean-action bean="cartController" method="changeQuantities">

 	<method-arguments><argument expression="flowScope.viewCommand"/></method-arguments>

 	<method-result name="viewCommand" scope="flow"/>

 </bean-action>

However Spring WebFlow has many aspects that would stop you from using it for entire site. Click-around navigation and SWF do not play well together.
So what I need is ability to define OGNL expression in Spring coonfig without using SWF. What looked scarry on first sight turned to be extremely easy task.
I did some prototyping of idea and here is what I got in spring config file:

 <bean id="profileView" class="com.cochlear.mcc.web.GenericFormController">

 	<property name="formView" value="profileView"/>

 	<property name="manager"><ref bean="profileManager"/></property>

 	<property name="viewScript"><value>manager.getProfile()</value></property>

 </bean>

 <bean id="profileForm" class="com.cochlear.mcc.web.GenericFormController">

 	<property name="formView" value="profileForm"/>

 	<property name="manager"><ref bean="profileManager"/></property>

 	<property name="modelClass"><value>com.cochlear.mcc.profile.model.ProfileDTO</value></property>

 	<property name="viewScript"><value>manager.getProfile()</value></property>

 	<property name="postScript"><value>manager.updateProfile(#object)</value></property>

 	<property name="successView" value="redirect:profile.view"/>

 </bean>

Not as clear as in SWF maybe but enough to prove the idea. It is concise, it does the job. You do not have to write FormActions for trivial things.
Here is what I have in GenericFormController:

public class GenericFormController extends SimpleFormController{

 protected Object manager;

 protected String viewScript;

 protected String postScript;

protected Object formBackingObject(HttpServletRequest request) throws ServletException, InstantiationException, IllegalAccessException {

 	try {

     	if(StringUtils.hasText(viewScript)){

 			OgnlContext context= new OgnlContext();

 			populateOgnlContextCommon(context, request);

 			Object expr = Ognl.parseExpression(viewScript);

 			Object res=Ognl.getValue(expr, context, this);

 			return res;

     	}else{

     		return getCommandClass().newInstance();

     	}

 	} catch (OgnlException e) {

 		e.printStackTrace();

 		throw new ServletException(e);

 	}

    }

protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response,

                                    Object commandObject, BindException errors) throws Exception {

Object command = getCommandClass().cast(commandObject);

 	try {

     	if(StringUtils.hasText(postScript)){

 			OgnlContext context= new OgnlContext();

 			context.put("command", command);

 			populateOgnlContextCommon(context, request);

 			Object expr = Ognl.parseExpression(postScript);

 			Ognl.getValue(expr, context, this);

     	}else{

     		throw new ServletException("No postScript specified");

     	}

 	} catch (Exception e) {

 		errors.reject(null, "Error:"+e.getMessage());

 		return showForm(request, errors, getFormView());

 	}

return new ModelAndView(getSuccessView());

    }

protected void populateOgnlContextCommon(OgnlContext context, HttpServletRequest request){

 	  context.put("request", request);

 	  context.put("session", request.getSession());

 	  context.put("user", SecurityContextHolder.getContext().getAuthentication().getPrincipal());

    }

// Getters and Setters here ..

 // ...

}

When I have time I will do something more production grade. For now I just glad to know that it is achievable and quite simple actualy.

DiggIt | del.icio.us

Runing Tomcat as Linux service

January 21, 2007

Not big deal but I am bit tired to google for this script each time I setup new box. Now I know where to get it without spending two valuable extra minutes to google. First create /etc/rc.d/init.d/tomcatd :

#!/bin/bash  
#  
# Startup script for Tomcat  
#  
# chkconfig: 345 84 16  
# description: Tomcat jakarta JSP server  
TOMCAT_HOME=/usr/share/apache-tomcat-5.5.20  
TOMCAT_START=$TOMCAT_HOME/bin/startup.sh  
TOMCAT_STOP=$TOMCAT_HOME/bin/shutdown.sh  
#Necessary environment variables  
export JAVA_HOME=”/usr/share/jdk1.5.0_10?  
export CATALINA_HOME=”/usr/share/apache-tomcat-5.5.20?  
#export LD_KERNEL_ASSUME=”2.2.5?  
# Source function library.  
. /etc/rc.d/init.d/functions  
# Source networking configuration.  
. /etc/sysconfig/network  
# Check that networking is up.  
[ ${NETWORKING} = “no” ] && exit 0  
#Check for tomcat script  
if [ ! -f $TOMCAT_HOME/bin/catalina.sh ]  
then  
    echo “Tomcat not available…”  
    exit  
fi  
start() {  
    echo -n “Starting Tomcat: “  
    su - tomcat -c $TOMCAT_START  
    echo  
    touch /var/lock/subsys/tomcatd  
# We may need to sleep here so it will be up for apache  
    sleep 3  
#Instead should check to see if apache is up by looking for httpd.pid  
}  
stop() {  
    echo -n $”Shutting down Tomcat: “  
    su - tomcat -c $TOMCAT_STOP  
    rm -f /var/lock/subsys/tomcatd  
    echo  
}  
status() {  
    ps ax –width=1000 | grep “[o]rg.apache.catalina.startup.Bootstrap start” | awk ‘{printf $1 ” “}’ | wc | awk ‘{print $2}’ > /tmp/tomcat_process_count.txt  
   read line

Add user tomcat. Please note that it is normal user with his own home. Many times it was very useful.

adduser tomcat

Set JAVA_HOME for all users in /etc/profile.d/java.sh . When we run ’su – tomcat’ this script will set up our environment:

export JAVA_HOME=/usr/share/jdk1.5.0_10

Give enough permissions to tomacat:

chown tomcat /usr/share/apache-tomcat-5.5.20/ -R

Now you are able to run tomcat with

service tomcatd start

The last thing is to run it when system boots:

chkconfig –add tomcatd  
chkconfig tomcatd on

Done

POSTable HTML links

January 17, 2007

When building web sites you often have to produce POST request on user’s actions. Many times without having user – editable form fields. Server just expects you to send POST. The standard solution is to make hidden form, hardcode some fields value and dynamically populate other values when user presses submit button. It does the job. But the code is spoiled with these pseudo forms and, I believe, you never gonna like it.

There is other approach that is much more concise and programmer friendly (tm:) . The trick is to construct and submit form on-the-fly. Let’s start with JavaScript function that exploits Prototype:
Read the rest of this entry »

Discovering Spring MVC

August 28, 2006

Spring MVC is not taken seriously jet because of almost absent documentation. For 2.0 version they wrote couple more paragraphs. But still only pages 214-250 devoted to Spring MVC itself. Many features left undocumented.

For my recent project I had to build a form having 6 different sets of fields. Depending on selected value in combo-box I process specific set. The rest of fields are ignored. That was easy to decide but how to tell Spring no to bind some fields?

One approach is to process input manually disabling automatic binding by overriding supressBinding function:

protected boolean suppressBinding(HttpServletRequest request) {
  return false;
}

Will work but leaves whole burden of binding on your shoulders. You do not want that. The other approach is letting Spring know which fields you want to process and which not. Take a look:
Read the rest of this entry »

Ascon:use-case diagram

August 20, 2006

Using of Ascon only available for registered users. We need simplest possible register and login functionality.

UML_ascon_usecaseAscon user interface mainly provide functionality for managing(CRUD) user’s addressbook and CallJobs. In list of CallJobs user should also have ability to see kind a report for completed jobs.

When CallJob executed we need to place a call and when answered read out the text of message. After that JobCall is considered as completed. If nobody answers the call we mark it as dismissed. In next versions we might want to introduce “redial schedule” for repeating unaswered calls until completion.

For incoming calls we are going to have conventional IVR service with arbitrary dialog.

Operator has all functionality as normal user, report for all users, report for all JobCalls and ability to manage Carriers.

Improvement of JSON to JAVA marshalling with JSON-RPC

August 16, 2006

During debugging one of my porjects I’ve spoted the following code in BeanSerializer.java from JSON-RPC library:


public Object unmarshall(SerializerState state, Class clazz, Object o)
...
Method setMethod = (Method)bd.writableProps.get(field);
if(setMethod != null) {
    ...
    setMethod.invoke(instance, invokeArgs);
    ...
}

The class is responsible of transforming Json notation to your Java Bean. Looking at code I realised that when no setter is present for field(or you mistyped field name in JSON) nothing happens. Nothing is set on the Bean obviously and no exception is thrown! Is some situation it makes sence. Silently dropping of absent fields is nice feature when you write backward compatible code or similar. But in most cases you want to rise an exception when field name does not match to Java bean fields. So I suggest to modify this code like following:
Read the rest of this entry »

Watchdog for tomcat

August 16, 2006

Here is just short script that restarts tomcat when it wrizes. It happens to our prod during peak load. You need to place inder webapps/ROOT directory a file isalive.html with one word ‘YES’ inside. Or alternatively modify a script and access default index.jsp.



#!/bin/sh
HOST=127.0.0.1
PORT=8080

#infinite loop
while [ 1 ]
do
	#try to access tomcat's page
	RES=`wget -O - -o /dev/null --proxy=off http://${HOST}:${PORT}/isalive.html | awk '{ print $1 }'`
	echo got ${RES}
	#decide on reply
	if [ "$RES" = "YES" ]
	then
		echo tomcat is responding on $HOST:$PORT
	else
		echo tomcat seems to be dead.
		echo Killing...
		for thepin in `ps -Af | grep -v grep | grep tomcat | grep catalina | awk '{ print $2 }'`
		do
			kill -9 ${thepin}
		done
		echo Starting...
		sudo -u tomcat /usr/local/tomcat/bin/startup.sh
	fi

sleep 60
done

Java technologies popularity in Sydney

August 13, 2006

AuJava logo

Here is just some numbers from jobserve.com.au. All keywords were prefixed with Sydney AND Java AND statement. The search for Sydney AND Java only gives 500 matching jobs.
AppServer:

  1. WebSphere – 56
  2. WebLogic – 47
  3. Tomcat – 41
  4. JBoss – 32
  5. Sun -21
  6. JRun – 3
  7. GlassFish – 0
  8. Geronimo – 0

Read the rest of this entry »

Generic DAO and more

August 9, 2006

Since Java 5 introduced new generics feature many aspects of our Java coding has changed. DRY approach to many tiers in J2EE soared and become common place. Even such a conservative monsters as IBM come up with nice generic-based patterns. Have a look at this really good article Dont repeat the DAO. They did not invent something new but rather summarised bit and pieces in pretty well done generic DAO. However if you have simple web-based CRUD project you can go even further and generify your managers. Most of the time managers do exactly the same job providing additional wrapper around DAO. So it is the same CRUD as we had in DAO but DataBase -agnostic. So lets have a look at our DAO:
Read the rest of this entry »


Follow

Get every new post delivered to your Inbox.