Showing posts with label Struts 2. Show all posts
Showing posts with label Struts 2. Show all posts

Sunday, March 30, 2008

JUNIT with Struts 2

lets c how to write Junit test cases for an application written in Struts2. The biggest problem i encountered is that theres hardlt any documentation abt this... by struggling over the net i discovered a way to circumvent the problem. The code goes as follows.

basically here we are see if the Entries made in Struts.xml (i.e. that we give using <> tag etc... ) is working fine or not.

Create a base Test case:
package com.company

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

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

import org.apache.struts.mock.MockServletConfig;
import org.apache.struts.mock.MockServletContext;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.util.StrutsTestCaseHelper;

import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;

import junit.framework.TestCase;

public class BaseS2TestCase extends TestCase {
private Dispatcher dispatcher;
protected ActionProxy proxy;
protected static MockServletContext servletContext;
protected static MockServletConfig servletConfig;
protected HttpServletRequest request;
protected HashMap requestParameters = new HashMap();
protected HttpServletResponse response;

public BaseS2TestCase(String name) {
super(name);
}

/**
* Creates action class based on namespace and name
*
* @param clazz
* Class for which to create Action
* @param namespace
* Namespace of action
* @param name
* Action name
* @return Action class
* @throws Exception
* Catch-all exception
*/
@SuppressWarnings("unchecked")
protected T createAction(Class clazz, String namespace, String name)
throws Exception {
dispatcher = StrutsTestCaseHelper.initDispatcher(null);
// dispatcher = Dispatcher.getInstance();
proxy = dispatcher.getContainer().getInstance(ActionProxyFactory.class)
.createActionProxy(namespace, name, null, true, false);
proxy.getInvocation().getInvocationContext().setParameters(
requestParameters);

// do not execute the result after executing the action
proxy.setExecuteResult(true);

// set the actions context to the one which the proxy is using
ServletActionContext.setContext(proxy.getInvocation()
.getInvocationContext());
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
ServletActionContext.setServletContext(servletContext);
return (T) proxy.getAction();
}

/**
* The method(X) mentioned in < name="..." method="X" class="C"> tag is
* invoked on the class(C) and the string-result is returned.
*
* @return: action result, eg: SUCCESS, FAILURE etc as returned by the
* action method
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
protected String execActionMethod() throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
Object action = proxy.getAction();
Method method = action.getClass().getMethod(proxy.getMethod(), null);
Object result = method.invoke(action, null);
return (String) result;
}
}


and now extend this class and get the juint running :)

public class newTest extends EdsBaseTestCase {

public EdsWizardTest(String name) {
super(name);
}

protected void setUp() throws Exception {
super.setUp();
}

protected void tearDown() throws Exception {
super.tearDown();
}

public void testEventAttributes() throws Exception {
EdsWizard action = createAction(EdsWizard.class, "/eds",
"eventAttributes");
// String method = proxy.getMethod();
String exec = execActionMethod(); // action.eventAttributes();
assertEquals(exec, "success");
}
}

Thats it. You are done. Please let me know if u see any issues with this approach.

cheers,
coffee

Friday, February 22, 2008

surprising experience with Struts2

The action class has a Dto, which contains a Map&lt;String, String&gt; object. I want to 'put' an entry into it from the UI layer /jsp. or in otherwords... i will say &lt;s:textfield name="dto.map['xyz']" /&gt; and say the user enters 123 into the text field then it will result into an entry: ["xyz","123"]. Till here things are fine but in one case this wouldn't work...!!! Its a catch.


suppose the dto is enclosed in session scope then the same would result into ["xyz",""] i.e. null string. I found that this is never getting updated and when i removed the dto from the session scope then it gave ["xyz","123"] result. so whats the session scope doing here?

i tried thisway in the jsp:
&lt;s: textfield name="dto.map['xyz']" /&gt;
&lt;s:property value="dto.map" /&gt;

this resulted a textbox and a text: [xyz,''] thats the catch: i.e. when the jsp is being rendered itself the map is being put with key xyz if its not present in the map. and for this reson the text [xyz,] is being printed... supposing that this is not the case then it would have rendered a text as [,] i.e. empty map.

for this reason when the textbox is trying to put the value into the map, as the key is already present its unable to do so...

To discover this it took me 2 days of effort.. may b it saves some of ur efforts and stops u from reinventing the wheel...

thats for now.. watch the space for more interesting things to come up...

Tuesday, January 1, 2008

DWR with struts 2

Struts-2 uses dwr(direct web remoting) to validate the forms; atleast 2.0.x version does it and struts promises that ajax validation would be available from 2.1x versions... i was working with checkboxes in a jsp (using struts2.0.9) the following is the issue:

there are 3 checkboxes in the form, c1,c2,c3 and now say u checked the box-c2 or u didnt check any of the boxes...; the idea is to validate the checkboxes; the surprise is that always the c3 would be submitted irrespective of what box is checked... i found the problem with the validateClient.js file. The same can be reproduced (simple by edititng quizAction.java of struts-showcase application) any idea asto what can be done???


i think that i should handle this by creating a new theme... let me post the same in JIRA. :)

--
coffee


Powered by ScribeFire.