Author Archive

Test of Spring MVC annotations

Spring 3 MVC annotation based controller make Unit Testing real easy and straight forward. Since you don’t have to implement any interface or extend super classes for controller as you used to do in Spring 2, you can call methods in controller directly for Unit Testing without Spring or any other container.

With Spring MVC annotation, a controller can be defined as simple as:

@Controller

public class SimpleController {

@RequestMapping(value=”/simple”, method=RequestMethod.GET)

public @ResponseBody String simple() {

return “Hello world!”;

}

}

To test this controller, you can treat it as a POJO. Methods in controller can be called and tested directly:

public class SimpleControllerTests {

@Test

public void test() {

SimpleController controller = new SimpleController();

assertEquals(“Hello world!”, controller.simple());

}

}

If you want to do integration test, Spring TestContext Framework makes it simple. The Spring TestContext Framework provides generic, annotation-driven unit and integration testing support. The easiest way to use Spring TestContext Framework is to use @RunWith & @ContextConfiguration to load Spring container for unit and integration test. It will support for loading application contexts, dependency injection of test instances, transactional test and so on. The Mock object is provided by TestContext Framework as well.

Here is a simple example of using TestContext Framework to do integration testing. We want to test followings in this test:

  • Spring application context is loaded properly.
  • Appropriate handlerAdapter is used.
  • Testing request method & URL mapping
  • Testing @ResponseBody

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(“/servlet-context.xml”)

public class SimpleControllerIntegrationTests {

@Autowired

Private AnnotationMethodHandlerAdapter handlerAdapter;

Private MockHttpServletRequest request;

Private MockHttpServletResponse response;

Private SimpleController controller;

@Before

public void setUp() {

request = new MockHttpServletRequest();

response = new MockHttpServletResponse();

controller = new SimpleController();

}

@Test

public void testSimple() throws Exception {

request.setMethod(“GET”);

request.setRequestURI(“/simple”);

handlerAdapter.handle(request, response, controller);

assertEquals(“Hello world!”, response.getContentAsString());

}

}

In this code, we use @RunWith(SpringJUnit4ClassRunner.class) to setup JUnit 4.5+ environment with Spring. Using @ContextConfiguration(“/servlet-context.xml”) to load application contexts (servlet-context.xml) for test class, all tests in this class will share the configured ApplicationContext . We use Mock objects from Spring for request and response object. As you can see, setup Request URL & method is straight forward.

It should be fairly easy to extend this to more complex examples testing @ModelAttribute, @RequestParam, @PathVariable, @RequestHeader, etc.

Could not load file or assembly ‘apache fop.net’ or one of its dependencies

By George Zheng

When we deploy one of our web sites to a 64 bit web server, we get following error: “Could not load file or assembly ‘apachefop.net’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

This web site is using fop.net to generate the PDF for printing. After investigation, we realize the fop.net can’t run on IIS with 64-bit version of ASP.NET.

IIS 6.0 on a 64-bit hardware supports both the 32-bit version of ASP.NET and the 64-bit version of ASP.NET. However IIS 6.0 does not support running both modes at the same time on a 64-bit version of Windows.  Here are the steps to run the 32-bit version of ASP.NET 2.0 on IIS:

  1. Click Start, click Run, type cmd, and then click OK.
  2. Type the following command to enable the 32-bit mode:
    cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 1
  3. Type the following command to install the version of ASP.NET 2.0 (32-bit) and to install the script maps at the IIS root and under:
    %SYSTEMROOT%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -i
  4. Make sure that the status of ASP.NET version 2.0.50727 (32-bit) is set to Allowed in the Web service extension list in Internet Information Services Manager.

Useful Links

How to switch between the 32-bit versions of ASP.NET 1.1 and the 64-bit version of ASP.NET 2.0 on a 64-bit version of Windows

Process XML in C#.net

By George Zheng

XML has been used in a lot of places for transferring data because of its platform independence and its simple, text-based, self-describing format. It is a common requirement for preparing and consuming XML data. Microsoft provides several convenience tools to help developers deal with XML under .NET platform.

  1. System.Xml.XmlTextReader/System.Xml.XmlTextWriter
  2. System.Xml.Serialization.XMLSerializer
  3. System.Xml.Linq

XmlTextReader/XmlTextWriter
XmlDocument objects are easy to use for navigating the DOM copying, modifying, or inserting nodes. However, they can also use a large amount of memory to store the entire DOM of a large XML string in memory. Because of this, the XmlTextReader and XmlTextWriter classes can be used for stream based manipulation of an XML string.
Let’s say you have an XML as:
<?xml version=1.0 encoding=utf-8 ?>
<user id=1>
<firstname>George</firstname>
<lastname>Zheng</lastname>
</user>

Following code will read it into a user object.

User user = new User();
XmlTextReader reader = new XmlTextReader(“user.xml”);

while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == “user”)
{
user.Id = Convert.ToInt32(reader.GetAttribute(“id”));
}
if (reader.Name == “firstname”)
{
user.Firstname = reader.ReadElementContentAsString();
}
if (reader.Name == “lastname”)
{
user.Lastname = reader.ReadElementContentAsString();
}
}
}
With XmlTextWriter, following code will generate XML string:

StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlTextWriter writer = new XmlTextWriter(sw);

writer.WriteStartElement(“user”);
writer.WriteAttributeString(“id”, user.Id.ToString());
writer.WriteElementString(“firstname”, user.Firstname);
writer.WriteElementString(“lastname”, user.Lastname);
writer.WriteEndElement();

return sb.ToString();

XMLSerializer

If you don’t want to deal with the XML element by element, .NET provides an alternative approach to convert object instance to XML and read the data back – XML Serialization. This is more convenience for a complex object.

TextReader tr = new StringReader(xml);
XmlSerializer s = new XmlSerializer(typeof(User));
User user = (User)s.Deserialize(tr);

Following code can be used to serialize the object:

XmlSerializer s = new XmlSerializer(typeof(User));
TextWriter writer = new StringWriter();
s.Serialize(writer, user);
writer.Flush();
string xml = writer.ToString();
writer.Close();

The object can be a complex object like:

public class User
{
[XmlAttribute("id")]
public int Id { get; set; }

[XmlElement("firstname")]
public string Firstname { get; set; }
[XmlElement("lastname")]
public string Lastname { get; set; }

[XmlArray("projects")]
[XmlArrayItem("project", typeof(Project))]
public List<Project> Projects { get; set; }
}

public class Project
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
}

As you can see, serializer attributes can be used to specify how the object’s properties map to XML entities. I’m not going to discuss these attributes here. Details can be found from Useful Links below.

LINQ

In some case, convert the whole XML may not be a good idea. Linq provides a convenience approach to query a complex XML.

Here is the example account feed response from Google Analytics API

<?xml version=1.0 encoding=UTF-8?>
<feed xmlns=http://www.w3.org/2005/Atom xmlns:openSearch=http://a9.com/-/spec/opensearchrss/1.0/ xmlns:dxp=http://schemas.google.com/analytics/2009>
<id>http://www.google.com/analytics/feeds/accounts/abc@test.com</id>
<updated>2009-06-25T03:55:22.000-07:00</updated>
<title type=text>Profile list for abc@test.com</title>
<link rel=self type=application/atom+xml href=http://www.google.com/analytics/feeds/accounts/default/>
<author>
<name>Google Analytics</name>
</author>
<generator version=1.0>Google Analytics</generator>
<openSearch:totalResults>12</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>12</openSearch:itemsPerPage>
<entry>
<id>http://www.google.com/analytics/feeds/accounts/ga:1174</id>
<updated>2009-06-25T03:55:22.000-07:00</updated>
<title type=text>www.googlestore.com</title>
<link rel=alternate type=text/html href=http://www.google.com/analytics/>
<dxp:tableId>ga:1174</dxp:tableId>
<dxp:property name=ga:accountId value=30481/>
<dxp:property name=ga:accountName value=Google Store/>
<dxp:property name=ga:profileId value=1174/>
<dxp:property name=ga:webPropertyId value=UA-30481-1/>
<dxp:property name=ga:currency value=USD/>
<dxp:property name=ga:timezone value=America/Los_Angeles/>
</entry>
<entry>
<id>http://www.google.com/analytics/feeds/accounts/ga:6284812</id>
<updated>2009-01-06T17:39:33.000-08:00</updated>
<title type=text>www.googlestore.com (Test Team)</title>
<link rel=alternate type=text/html href=http://www.google.com/analytics/>
<dxp:tableId>ga:6284812</dxp:tableId>
<dxp:property name=ga:accountId value=30481/>
<dxp:property name=ga:accountName value=Google Store/>
<dxp:property name=ga:profileId value=6284812/>
<dxp:property name=ga:webPropertyId value=UA-30481-1/>
<dxp:property name=ga:currency value=USD/>
<dxp:property name=ga:timezone value=America/Los_Angeles/>
</entry>
</feed>

With following code, you will get ID, Title and AccountName for each entry.

XDocument doc = XDocument.Parse(xml);
XNamespace dxpSpace = doc.Root.GetNamespaceOfPrefix(“dxp”);
XNamespace defaultSpace = doc.Root.GetDefaultNamespace();

IEnumerable<Account> entries =
from en in doc.Root.Descendants(defaultSpace + “entry”)
select new Account
{
ID = en.Element(defaultSpace + “id”).Value,
Title = en.Element(defaultSpace + “title”).Value,
AccountName =
en.Elements(dxpSpace + “property”).Where(
xe => xe.Attribute(“name”).Value == “ga:accountName”).First().
Attribute(“value”).Value
};

Useful Links

Insert XML Nodes Using XmlTextReader and XmlTextWriter
Using the XmlSerializer Attributes
Added Google Analytics Reader for .NET


download Download source code

Maintaining the Active Tab in TabContainer Control

by George Zheng

Problem

AJAX Control Toolkit has a neat control – TabContainer, to allow you create tabs on your web page easily. However, one problem with it is that when user refreshes the page, it defaults back to the first tab. This will cause user confusion if you have pagination in third tab let’s say. Every time, when user click a page number on third tab. Page get refreshed and it should show third tab, not the first tab.

Solution

The reason refreshed page always show the first tab is, in fact, one of the benefits of the tab control – switching between tabs doesn’t cause a post back. This is a pure client activity. When server prepares the page, it has no idea which tab is the active tab on client side. So server will set first tab as active tab by default.
Read the rest of this entry »