Maven – fixing classpath issues for tests

November 10th, 2008

We had problems with tests not finding files that we usually package outside the jar. One of such files was log4j.xml and other files were configuration files for spring framework. We need to pass full path to the log4j file, so that we don’t have to rely on class path priorities to look it up. Given that log4j.xml is such a widely used file, it is probable that one of the dependent jar would have a copy in the archive – so we can pick up the wrong file by mistake. On the other hand, we want to have our spring framework configuration files in the class path, but outside the jar. This way we can modify the configuration on the fly if we need to. So to setup integration test case, we needed to get the full path to the log4j.xml file and adding a directory to the class path for test only.
Here is how to do that:
public static String getFullPath(Class c, String name){
     ClassLoader cl = c.getClassLoader();
     URL url = cl.getResource(name);
     return url != null ? url.getPath() : null;
}
and for adding class path:
<plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-surefire-plugin</artifactId>
     <configuration>
     <additionalClasspathElements>
          <additionalClasspathElement>./src/main/config/</additionalClasspathElement>
          <additionalClasspathElement>./mymodule/src/main/config/</additionalClasspathElement>
      </additionalClasspathElements>
    </configuration>
</plugin>

Linking between a controller page and a non-initail page of Spring MVC Wizard

October 28th, 2008

For one of the projects where I used Spring MVC 2.5 I had to link a view page with the second page of edit wizard. The reason for the linking is this that view page contains enough information to bypass the first wizard screen for editing the information person is viewing. Here is how to do it.

In the target wizard controller you will need to overwrite the following three methods: two for getting the names of attributes stored in a session and one for getting the page number from request attribute first then request parameter. 
Since wizards work with session based forms, you will need to put the form in the session. To do that, you would need to know the attribute key in your controller. The key value is available in the super class, so you need to make the method visible.

public String getFormSessionAttributeName(HttpServletRequest request) {       
   return super.getFormSessionAttributeName(request);
}

Same with getting the page attribute, which you will need to control which page of the wizard you will link to.

public String getPageSessionAttributeName(HttpServletRequest request) {  
   
return super.getPageSessionAttributeName(request);
}

The other thing is that you will need to pass in the page number, which you can only pass as request argument, not request parameter as expected by the super class. So here is how you can do it:

protected int getTargetPage(HttpServletRequest request, int currentPage) {       
  
Enumeration requestNamesEnum = request.getAttributeNames();
   while (requestNamesEnum.hasMoreElements()) {           
          
String requestName = (String) requestNamesEnum.nextElement();
           
          
if (requestName.startsWith(AbstractWizardFormController.PARAM_TARGET)) {
                   
for (int i = 0; i < WebUtils.SUBMIT_IMAGE_SUFFIXES.length; i++) {
                      
String suffix = WebUtils.SUBMIT_IMAGE_SUFFIXES[i];
                      
if (requestName.endsWith(suffix)) {
                                  
requestName = requestName.substring(0, requestName.length() – suffix.length());   
                        
}
                 
}
              
 return Integer.parseInt(requestName.substring(AbstractWizardFormController.PARAM_TARGET.length()));   
            
}
       
} 
    
return WebUtils.getTargetPage(request, PARAM_TARGET, currentPage);
}

Now in your controller you need to prepare all the parameters to call the wizard:

HttpSession session = request.getSession(); 
MyWizardForm wizardForm = new MyWizardForm();
  
wizardForm.setDataId(viewForm.getDataId());
 // populating information from view screen
wizardForm.setMoreData(viewForm.getMoreData());
 
EditWizardController tempEditWizardController = new EditWizardController();
 
request.setAttribute(tempEditWizardController.getPageSessionAttributeName(request), new Integer(0)); //as if user had posted data on page 0
request.setAttribute(“_target1″,”_target1”); //and the landing page should be page 2, after page 1 is validated.
session.setAttribute(tempUniverseEditWizardController.getFormSessionAttributeName(request), wizardForm);

return new ModelAndView(“forward:editUniverse.htm”);

 

And that is it!

Testing Struts Apps With Maven

September 11th, 2008

While switching my configuration manager project from Maven 1 to Maven 2, I had to figure out how to add WEB-INF/web.xml located in src/main/webapp directory to the Maven test class path, so that MockStrutsTestCase would be able to access it. After a bit of digging on the net, and experimenting, I found an easy way of accomplishing it. Here is what needs to be added to your POM:
<plugins>
<
plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/src/main/webapp</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugin>

After I’ve added this fragment, all the tests I’ve ported passed! Hurray!


Good article on Building and Deploying with Maven 2

September 3rd, 2008

We are using Maven 2 as part of our build/deploy/dependency management tool. It is great in dependency management, code quality reporting, deploying to repositories, as well as having a very uncomplicated build script and not having to store our Idea or Eclipse project files (since we have them generated). The biggest problem we discovered so far, was that maven is not so well suited to deploy projects into different environments – development, qa, production.  So, if you are developing reusable components – go for Maven, it will make your builds so much easier. If you have to build a product and deploy it to different servers (dev, qa, int, prod and prod_bcp) – it might not be as easy. After a long search on how other people have struggled with this problem, I found a good article The Pain of migrating from Ant to Maven and even though it does not solve my problem, it describes very well the pain points I felt when I worked with Maven.

Handling java.util.Date in Spring MVC

August 6th, 2008

A lot of times I needed to display and edit data that has date information in it. For example, user registration form might have a birthday field. I do want that field to be java.util.Date and be save in the database as a date, but when rendering to JSP I used to have to convert it to/from a text field. Not anymore! I started using custom PropertyEditorSupport for Date processing. To use this feature, you need to follow 3 steps:

First, you need to create a custom PropertyEditorSupport. Here is the one I used for java.util.Date:

package foo;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.text.ParseException;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;

/**
 * @author Henry Naftulin
 * @since Aug 4, 2008
 */
public class DatePropertyEditor extends PropertyEditorSupport {
  Logger log = Logger.getLogger(DatePropertyEditor.class);
  String[] formats = {"yyyy-MM-dd", "MM/dd/yyyy", "MM/dd/yy"};

Date defaultDate = new Date(0L);

public void setAsText(String textValue) {
  if (textValue == null) {
  setValue(defaultDate);
  return;
  }
  Date retDate = defaultDate;
  try {
  retDate = DateUtils.parseDate(textValue, formats);
  } catch (ParseException e) {
  log.error("Cannot parse " + textValue + " as date.", e);
  }
  setValue(retDate);
  }

}

Second, I need to register the custom property editor with my Spring MVC controller, which I do by overwriting the following method:

protected void initBinder(HttpServletRequest req, ServletRequestDataBinder binder) throws Exception {
  binder.registerCustomEditor(Date.class, new DatePropertyEditor());
  }

And that is it: you can just render you date field in the JSP and dates typed into the text fields would be converted from the String representation to java.util.Date!

Configuring a web server instance with JBoss

July 4th, 2008

It is not hard to configure a jboss web server instance on the same machine with other instances. You might want to look at http://wiki.jboss.org/wiki/ConfiguringMultipleJBossInstancesOnOneMachine for explanation on why would you need it. To create a server instance copy default directory in jboss-xyz/server (or minimal if you are certain minimal server will do for you) and name it say my-webapp.  Go to your bin directory and copy run.bat (run.sh) and change the line:
“%JAVA%” %JAVA_OPTS% “-Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS%” -classpath “%JBOSS_CLASSPATH%” org.jboss.Main %*
to:
“%JAVA%” %JAVA_OPTS% “-Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS%” -classpath “%JBOSS_CLASSPATH%” org.jboss.Main -c my-webapp  %*

You might also have a -b option with your host name, like -b localhost as described in the article above. Now you also want you website to be on different port, not port 8080. To change the port, go to my-webapp/deploy/jbossweb-tomcatx.sar directory and change the ports there.

How to work with checkboxes in Spring MVC

June 26th, 2008

The usual problem with checkboxes in web environment is that if they were checked when you  are rendering the page and user unchecks them, there is no way by default to know that on back end. This is especially true when you are working with the ‘form’ for Spring wizard, since formBackingObject, where you can reset the checkbox boolean values to false,  is only called once for the first page and not on the subsequent pages. Spring MVC has a better solution to this problem, buy using the following construct:

<spring:bind path="command.myBooleanProperty"> 
        <input type="hidden" name="_<c:out value="${status.expression}"/>">
        <input type="checkbox" name="<c:out value="${status.expression}"/>" value="true"
            <c:if test="${status.value}">checked</c:if>/>
</spring:bind>

This approach is discussed on http://forum.springframework.org/archive/index.php/t-16093.html and on http://opensource.atlassian.com/confluence/spring/display/DISC/Working+with+Checkboxes

How to Host a Web Server at Home With Dynamic DNS

June 6th, 2008

A good article by  Jeff Black oh how to host a web server at home could be found at http://codebeneath.blogspot.com/2007/08/how-to-host-web-server-at-home-with.html In my case, I’ m trying to find a good service that would host my web-apps and would not be too expensive – so I might try his approach.

Finding appropriate colors for your site and for development

June 2nd, 2008

It is much easier to choose the background or foreground colors for your site with a visual map of colors. One of the maps could be found at: http://i105.photobucket.com/albums/m210/royaladybug/RL_Site/colorchart.gif. Colors I’ve used for background are light pastel colors #CCFF66, #CCFFFF, #CCFFCC, #FFFF99, #99FFFF, #99FF99, #CCCC99, #CCCCFF, #CCCCCC, #CC99FF, #FF99FF,#66CCFF which work really well with black foreground color. The best way of course is to use CSS to define you background colors. So for example for tables cells I’ve used the following format:
in css file td.bgcolor1 { background-color: #CCFF66 } in jsp file: <td class="bgcolor1">. You can choose a better description for colors or have css refer to functional elements on your site.

I’ve released configuration manager 1.5

May 30th, 2008

Configuration Manager 1.5 can be controlled by using JMX. Unless otherwise instructed in the the configuration, configuration manager will register with the MBean Server. You will be able to see all the configurations and content and will also be able to reload configuration manager through the JMX console. Visit http://configmanager.sourceforge.net/ for more details.