Archive for February, 2008

Websphere command line admin

Up till now I have never used wsadmin for any Websphere server configuration operations. I always use the wonderfully designed Administration console application. But today I got stuck up with admin console while trying to undeploy an application. I was trying to undeploy the jetspeed war file, but for some reason admin console was throwing NullPointerException. I had to google for some time to figure out how to use the command line tool to undeploy the app. Hope this info helps others.

Go to the bin directory under your WAS installation. On my machine it is,

C:\RAD7.0\IBM\SDP70\runtimes\base_v61\bin

Run wsadmin.bat

wsadmin> $AdminApp uninstall *your-app-name*

wsadmin> $AdminConfig save

wsadmin> exit

Comments (1)

Struts Tip : How to build Multi-Event Actions?

Struts Action class uses a single execute method to handle all user requests. So what do we do when a screen has multiple submit buttons, each performing different operations. For eg:- the CRUD ( create, read, update, delete ) operations for a single entity. A general scenario that I have seen is, you have a List Page from which you can travel to a Detail Page by clicking on the line item link. Detail Page will have Update, Delete and Back buttons. List Page will have create button.List Page

update-page.png

So, do you need to write three action classes for handling these button events. No, there is something called DispatchAction and LookupDispatchAction in struts. The solution that I am going to describe here is based on extending ActionMapping.

The struts-config entry for these usecases will look like this,

<action path=”/displayList”
type=”com.unnisworld.employee.EmployeeAction”
name=”employeeForm”
validate=”false”
className=”com.unnisworld.struts.CustomActionMapping”>
<set-property property=”method” value=”doDisplayList” />
<forward name=”success” path=”/WEB-INF/pages/employee/list.jsp”/>
</action>

<action path=”/create”
type=”com.unnisworld.employee.EmployeeAction”
name=”employeeForm”
validate=”false”
className=”com.unnisworld.struts.CustomActionMapping”>
<set-property property=”method” value=”create” />
<forward name=”success” path=”/WEB-INF/pages/employee/list.jsp”/>
</action>

<action path=”/displayUpdate”
type=”com.unnisworld.employee.EmployeeAction”
name=”employeeForm”
validate=”false”
className=”com.unnisworld.struts.CustomActionMapping”>
<set-property property=”method” value=”doDisplayUpdate” />
<forward name=”success” path=”/WEB-INF/pages/employee/employee.jsp”/>
</action>

<action path=”/update”
type=”com.unnisworld.employee.EmployeeAction”
name=”employeeForm”
validate=”false”
className=”com.unnisworld.struts.CustomActionMapping”>
<set-property property=”method” value=”update” />
<forward name=”success” path=”/WEB-INF/pages/employee/list.jsp”/>
</action>

<action path=”/delete”
type=”com.unnisworld.employee.EmployeeAction”
name=”employeeForm”
validate=”false”
className=”com.unnisworld.struts.CustomActionMapping”>
<set-property property=”method” value=”delete” />
<forward name=”success” path=”/WEB-INF/pages/employee/list.jsp”/>
</action>

Only new thing in these action mapping entries are the set-property tags and the className attribute. The “method” property is not part of the standard struts ActionMapping class. You need to write a custom action mapping class to hold this property. This custom class is specified using the className attribute.

package com.unnisworld.struts;

import org.apache.struts.action.ActionMapping;

public class CustomActionMapping extends ActionMapping {

private static final long serialVersionUID = 1L;

private String method;

public String getMethod() {
return method;
}

public void setMethod(String method) {
this.method = method;
}

}

Now you need to write a top level action class which all other action classes in your project will extend.

This action class will have the logic to get the method name property from ActionMapping and invoke the correct method.

package com.unnisworld.struts;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.*;
import org.apache.struts.actions.DispatchAction;

/**
* Extends DispatchAction, actual logic for invoking action methods using reflection
* resides in the DispatchAction. We just need to override getMethodName function.
*/
public class BaseAction extends DispatchAction {

/**
* This is the only execute method in the entire action class hierarchy.
*/
public final ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

beforeExecute(mapping, form, request, response);

ActionForward af = super.execute(mapping, form, request, response);

afterExecute(mapping, form, request, response);

return af;
}

/**
* This method returns the method name from ActionMapping class.
* DispatchAction class uses this method to get the method name.
*/
protected String getMethodName(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response,
String parameter) throws Exception
{
return ((CustomActionMapping) mapping).getMethod();
}

/**
* This method is not used, but must be implemented to satisfy DispatchAction.
*/
protected String getParameter(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
return “nothing”;
}

protected void beforeExecute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
{

}

protected void afterExecute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
{

}

}

The BaseClass extends DispatchAction which has the logic to invoke methods using reflection. We just need to implement getMethodName method. beforeExecute and afterExecute are hook methods which can be overridden and used for initialization and cleanup operations.

Now look at CustomerAction which extends the BaseAction. It does not have execute method, instead it has methods like doDisplayList, create, update etc which are same as the method names given in struts-config file.

public class CustomerAction extends BaseAction {

public final ActionForward doDisplayList(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{

}

public final ActionForward create(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{

}

public final ActionForward doDisplayUpdate(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{

}

public final ActionForward update(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{

}

}

Now there is a crucial javascript part that is required to switch the action in EmployeeUpdate screen.

On the onClick event of Update and Delete buttons you should assign the correct action name to html form.

<script>

function switchAction(action) {

document.forms[0].action =action;

document.forms[0].submit();

}

<script>

<input type=”button” onClick=”switchAction(‘update’)” value=”Update” />

<input type=”button” onClick=”switchAction(‘delete’)” value=”Delete” />

Note :- This solution is a slight variation of the DispatchAction solution specified at struts site.

Comments (1)

What to do when redeploy fails on Tomcat?

I was just trying out some quick struts, spring, hibernate integration sample and got stuck up with this dirty issue.

My struts application deploys  successfully , but am not able to redeploy it. Tomcat does not show any error message.
While undeploying Tomcat is not able to cleanup some of the existing jar files inside the webapp.

Solution is simple,

Create a META-INF directory in your webapp parallel to WEB-INF and place a context.xml file inside it with following entry,

<Context reloadable=”true” antiResourceLocking=”true”> </Context>

See here for more explanation on the same.

Leave a Comment