Thursday, May 15, 2008
PortletWork: Testing Portlets with Jetty, Pluto and JWebUnit: "After my last two entries, I've gotten some questions about using pluto embedded in jetty to create automated integration tests for JSR 168 portlets. Using the maven-jetty-plugin for running the portlets is great for fast, iterative development. But it can't be used to run automated integration tests. Remembering an excellent article from Johannes Brodwall's blog about integration testing with Jetty and JWebUnit, I wanted to extend his approach to use the embedded jetty-pluto setup I have created. This turned out to be to be quite easy."
Thursday, May 01, 2008
Bare Bones Browser Launch for Java • • • Use Default Browser to Open a Web Page from portletUnit
One drawback of portletUnit is not being able to really see the rendered code. Using the ideas of the Bare Bones Browser Launch for Java, I am now able to display the rendered code.
The code I am using is:
I am creating a <base> for all the links so the images and CSS all get included as needed.
Bare Bones Browser Launch for Java • • • Use Default Browser to Open a Web Page from a Swing Application: "Java is often touted as the programing language of the Internet, so you would think Java might include a standard platform-independent mechanism to launch the user's default web browser. Unfortunately, this commonly needed feature is left to the application developer to build, and it's not particularly easy."
The code I am using is:
/**
* Show the response in a browser.
*
* @param response
* the response
* @param class1
* not used but the intent is to add a system propery regex that
* will control whether this page is loaded or not. Default will be none.
* @param id
* another regex system property will match against this. Default will be all.
* @throws Exception
* on error
*/
public static void showResponseInBrowser(WebResponse response, Class class1, String id) throws Exception {
String text = response.getText();
File f = File.createTempFile("httpUnit", ".html");
f.deleteOnExit();
PrintWriter fod = new PrintWriter(new FileOutputStream(f));
fod.print("<head><base href="'http://localhost'/"> </head>");
fod.print(text);
fod.close();
URL url = f.toURL();
openURL(url);
}
/**
* Bare Bones Browser Launch Version 1.5 (December 10, 2005) By Dem
* Pilafian. Supports: Mac OS X, GNU/Linux, Unix, Windows XP
*
* Example Usage: String url = "http://www.centerkey.com/";
* BareBonesBrowserLaunch.openURL(url); Public Domain Software -- Free to
* Use as You Like
*
* @param url
* the url to open
* @throws ClassNotFoundException
* getting class
* @throws NoSuchMethodException
* yes
* @throws SecurityException
* well
* @throws InvocationTargetException
* trying to invloke
* @throws IllegalAccessException
* trying to access
* @throws IllegalArgumentException
* bad arguement
* @throws IOException
* opening window
* @throws InterruptedException waiting
*/
public static void openURL(URL url) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, IOException, InterruptedException {
String osName = System.getProperty("os.name");
if (osName.startsWith("Mac OS")) {
Class fileMgr = Class.forName("com.apple.eio.FileManager");
Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] {String.class });
openURL.invoke(null, new Object[] {url.toString() });
} else if (osName.startsWith("Windows")) {
String cmdLine = "rundll32 url.dll,FileProtocolHandler " + url.toString();
Process exec = Runtime.getRuntime().exec(cmdLine);
exec.waitFor();
} else { // assume Unix or Linux
String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" };
String browser = null;
for (int count = 0; count < browsers.length && browser == null; count++) { if (Runtime.getRuntime().exec(new String[] {"which", browsers[count] }).waitFor() == 0) { browser = browsers[count]; } } if (browser == null) { throw new IllegalStateException("Could not find web browser"); } else { Runtime.getRuntime().exec(new String[] {browser, url.toString() });
}
}
}
I am creating a <base> for all the links so the images and CSS all get included as needed.
Friday, April 25, 2008
PortletUnit and Spring Portlet: Checking form validation errors
Spring Portlet allows validators to be added to SimpleFormController and objects that extend it. When the form is submitted, the validators are run and if any fail, the form is redisplayed with error messages indicating the problem areas. When testing with portletUnit, it is not obvious how to check if there were any form errors. Fortunately, using the render listener feature of PortletRunner, there is a simple way to check for validator errors.
WebResponse response = runner.getResponse(MAGIC_URL);
WebForm form = response.getFormWithID(PRINT_COMMAND);
form.setParameter(PrintData.PARAMETER_NAME_PURPOSE, REPORT_PURPOSE);
SubmitButton button = form.getSubmitButtonWithID(IDPRINT);
runner.addRenderListener(new PortletUnitRenderListener() {
});
form.submit(button);
The trick is to know that the BindException object is stored in the portlet session with the name org.springframework.web.portlet.mvc.RenderErrors. Simply install a listener and in the after method check to make sure there were no errors. You can use the same technique to ensure validation errors really do happen.
Spring Portlet allows validators to be added to SimpleFormController and objects that extend it. When the form is submitted, the validators are run and if any fail, the form is redisplayed with error messages indicating the problem areas. When testing with portletUnit, it is not obvious how to check if there were any form errors. Fortunately, using the render listener feature of PortletRunner, there is a simple way to check for validator errors.
WebResponse response = runner.getResponse(MAGIC_URL);
WebForm form = response.getFormWithID(PRINT_COMMAND);
form.setParameter(PrintData.PARAMETER_NAME_PURPOSE, REPORT_PURPOSE);
SubmitButton button = form.getSubmitButtonWithID(IDPRINT);
runner.addRenderListener(new PortletUnitRenderListener() {
public void after(Portlet arg0, RenderRequest request, RenderResponse arg2) throws Exception {
BindException bindException = (BindException) request.getPortletSession().getAttribute(
"org.springframework.web.portlet.mvc.RenderErrors");
assertEquals(0, bindException.getErrorCount());
}
public void before(Portlet arg0, RenderRequest arg1, RenderResponse arg2) throws Exception {
// EMPTY
}
BindException bindException = (BindException) request.getPortletSession().getAttribute(
"org.springframework.web.portlet.mvc.RenderErrors");
assertEquals(0, bindException.getErrorCount());
}
public void before(Portlet arg0, RenderRequest arg1, RenderResponse arg2) throws Exception {
// EMPTY
}
});
form.submit(button);
The trick is to know that the BindException object is stored in the portlet session with the name org.springframework.web.portlet.mvc.RenderErrors. Simply install a listener and in the after method check to make sure there were no errors. You can use the same technique to ensure validation errors really do happen.
Wednesday, January 30, 2008
Using portletUnit with Maven Surefire
I have been using portletUnit with Maven and surefire. There are a couple of issues that need to be worked around.
Issue 1: Dependencies
portletUnit still relies on 3 special jar files and these need to be added to your local maven repository. The effort to move to a more stable dependency tree is underway.
Issue 2: Jasper classpath
Out of the box, surefire forks the unit tests. Jasper does not like it. If JSPs are complaining about missing classes, try turning off forking with:
Issue 1: Dependencies
portletUnit still relies on 3 special jar files and these need to be added to your local maven repository. The effort to move to a more stable dependency tree is underway.
Issue 2: Jasper classpath
Out of the box, surefire forks the unit tests. Jasper does not like it. If JSPs are complaining about missing classes, try turning off forking with:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>never</forkMode>
</configuration>
</plugin>
Wednesday, May 02, 2007
What do I do when context.getRequestDispatcher (viewJsp); returns null?
Consider the following code:
private static String viewJsp = " hello.jsp";
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException
{
response.setContentType ("text/html");
PortletContext context = getPortletContext();
PortletRequestDispatcher dispatcher = context.getRequestDispatcher (viewJsp);
dispatcher.include(request, response);
}
dispatcher.include(request, response); throws a NullPointerException because the jsp "hello.jsp" can't be found. The jsp needs to be referenced from the root of the jar file:
private static String viewJsp = "/WEB-INF/jsp/hello.jsp";
private static String viewJsp = " hello.jsp";
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException
{
response.setContentType ("text/html");
PortletContext context = getPortletContext();
PortletRequestDispatcher dispatcher = context.getRequestDispatcher (viewJsp);
dispatcher.include(request, response);
}
dispatcher.include(request, response); throws a NullPointerException because the jsp "hello.jsp" can't be found. The jsp needs to be referenced from the root of the jar file:
private static String viewJsp = "/WEB-INF/jsp/hello.jsp";
Wednesday, April 26, 2006
JavaOne 2006
I will be attending JavaOne 2006 in San Francisco this year. It would be a great opportunity to meet some of you who find portletUnit useful and hear what would make it better, besides actually documenting it.
Tuesday, December 20, 2005
User Feedback
A user portletUnit has some initial problems getting it running. After some struggle, here is what they learned:
ah, figured it out! at least your example portlets tests are running :-)
what I had to change:
- I use a different castor.jar in my classpath (changed it to the one that comes with your code)
- add the example classes to my classpath (my fault, thought it would be by default when i define the folder WEB-INF)
- add ant.jar to my classpath

