Tag: Java
Using ResourceBundle and MessageFormat for Error Messages
by Frank Kim on Sep.07, 2009, under Java SE
When generating error messages, two Java utility classes, ResourceBundle and MessageFormat, are extremely practical and powerful. From the ResourceBundle JavaDoc:
Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a
Stringfor example, your program can load it from the resource bundle that is appropriate for the current user’s locale. In this way, you can write program code that is largely independent of the user’s locale isolating most, if not all, of the locale-specific information in resource bundles.This allows you to write programs that can:
- be easily localized, or translated, into different languages
- handle multiple locales at once
- be easily modified later to support even more locales
And from the MessageFormat JavaDoc:
MessageFormatprovides a means to produce concatenated messages in a language-neutral way. Use this to construct messages displayed for end users.
MessageFormattakes a set of objects, formats them, then inserts the formatted strings into the pattern at the appropriate places.
This is an example of an error message resource bundle, ErrorMessagesResources.properties.
userAlreadyExists=A user already exists with the name {0}.
passwordInvalid=Please enter a valid password.
This is an example of how you would use this resource bundle.
protected static final ResourceBundle resourceBundle =
ResourceBundle.getBundle("com.betweengo.ErrorMessageResources");
public boolean handleLogin(DynamoHttpServletRequest pReq, DynamoHttpServletResponse pRes) {
...
// user already exists
String errMsg1 = resourceBundle.getString("userAlreadyExists");
errMsg1 = MessageFormat.format(errMsg1, userName);
...
// password invalid
String errMsg2 = resourceBundle.getString("passwordInvalid");
...
}
Enums in Java
by Frank Kim on Sep.02, 2009, under Java SE

(Photo: Slide-together : now with cards by fdecomite)
Enums are highly useful data types introduced in Java SE 5.0. Though I love using them I often forget the exact syntax so this post is to remind me later how to use it.
public enum Example {
FOO,BAR
}
// create one using its name
Example myExample = Example.valueOf(“bar”.toUpperCase());
// if statement
if (myExample == Example.FOO) System.out.println(“FOO!”);
// switch statement
switch (myExample) {
case FOO: System.out.println(“FOO!”);
case BAR: System.out.println(“BAR!”);
}
// output as String using name
System.out.println(myExample.name());
For further reading please see Java’s Enums guide and Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects).
Encode URI
by Frank Kim on Mar.17, 2009, under Java SE
To encode an URI you can simply use Java’s URLEncoder’s encode method which has been available since JDK 1.4.
String encodedUri;
try {
encodedUri = URLEncoder.encode(uri, "UTF-8");
}
catch (UnsupportedEncodingException exc) {
// this should never happen
logger.warn("UTF-8 is not a supported encoding? Not encoding for now...", exc);
encodedUri = uri;
}
Dynamically generate sitemap.xml
by Frank Kim on Mar.02, 2009, under Servlet
sitemap.xml is a top level document on your website “for webmasters to inform search engines about pages on their sites that are available for crawling.” Google not surprisingly has its own documentation on how to improve your site’s visibility using sitemap.xml.
Typically sitemap.xml is a static file that is hand generated. But on large sites it makes more sense to generate this dynamically. One way to do this is to generate it on demand using a servlet. Here is my simple solution. I did not include the implementation for outputPages() since that will be specific to each application server’s DB hierarchy or web server’s file structure.
public class SiteMap extends HttpServlet {
protected static final String MIME_TYPE_XML = "application/xml";
// XML tags
protected static final String SITE_MAP_XML_INFO = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
protected static final String SITE_MAP_BEGIN =
"<urlset\n\txmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9\n\t\thttp://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">";
protected static final String SITE_MAP_END = "</urlset>";
protected static final String LOC_BEGIN = " <loc>";
protected static final String LOC_END = "</loc>";
protected static final String PRIORITY_BEGIN = " <priority>";
protected static final String PRIORITY_END = "</priority>";
protected static final String URL_BEGIN = "<url>";
protected static final String URL_END = "</url>";
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// set content type to be XML
response.setContentType(MIME_TYPE_XML);
// get writer
PrintWriter out = response.getWriter();
// output header
out.println(SITE_MAP_XML_INFO);
out.println(SITE_MAP_BEGIN);
// output pages
outputPages(request, out);
// output end
out.println(SITE_MAP_END);
out.close();
}
protected void outputPage(String uri, String priority, PrintWriter out, String urlStart) {
out.println(URL_BEGIN);
out.println(LOC_BEGIN + urlStart + uri + LOC_END);
out.println(PRIORITY_BEGIN + priority + PRIORITY_END);
out.println(URL_END);
}
}
Then you configure web.xml to use the SiteMap servlet.
<servlet>
<servlet-name>sitemap</servlet-name>
<servlet-class>com.upromise.olm.app.servlet.SiteMap</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sitemap</servlet-name>
<url-pattern>/sitemap.xml</url-pattern>
</servlet-mapping>
Sleep
by Frank Kim on Feb.26, 2009, under Java SE
I always forget how to sleep or wait in Java though it’s quite easy, just use the static method Thread.sleep.
For example:
// sleep the filter's wait interval
try {
Thread.sleep(filter.getWaitInterval() * 1000);
}
catch (InterruptedException exc) {
logger.error("unexpected interrupt", exc);
}
Sun has a tutorial calling Pausing Execution with Sleep.
Removing a Cookie
by Frank Kim on Feb.04, 2009, under Java
To remove a cookie the API suggests getting the cookie, setting its maxAge to 0, and then adding that cookie to the response. Digging around deeper I realized you also need to set the domain and the path. Here is an example of how to do this.
Cookie [] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals(COOKIE_WE_WANT)) {
cookie.setMaxAge(0);
cookie.setDomain(".betweengo.com");
cookie.setPath("/");
response.addCookie(cookie);
break;
}
}
It turns out though the catch is making sure that by the time you add the cookie to the response that the response has not already been committed. Previously the above code was in a tag but that was too late to modify the response. I moved this code to a filter and then it worked fine.
Unexplainable JSP Compilation Problem
by Frank Kim on Feb.04, 2009, under JSTL
I was getting a JSP compilation problem that I could not solve.
org.apache.jasper.JasperException: Unable to compile class for JSP
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:510)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
org.apache.jasper.JasperException: Unable to compile class for JSP
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:572)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:303)
java.lang.NumberFormatException: For input string: "${status.index}"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:447)
at java.lang.Integer.valueOf(Integer.java:553)
at org.apache.jasper.compiler.JspUtil.coerceToInt(JspUtil.java:752)
at org.apache.jasper.compiler.Generator$GenerateVisitor.convertString(Generator.java:2949)
The major problem was this was happening on the server but not locally. The compilation problem was occurring for this line.
<uportal:module definition="${module}" moduleIndex="${status.index}"/>
The moduleIndex value is “${status.index}”. Locally when the JSP compiler encounters this it knows to call my setter for moduleIndex that takes a String parameter. But on the server the JSP compiler seemed to insist on using the setter for moduleIndex that takes an integer parameter, hence the compilation problem.
I finally posted on the Sun Forums and with the help of evnafets I came up with two solutions.
- The correct solution is to upgrade my application to use JSTL 1.1. Then the JSTL expressions such as “${status.index}” will be evaluated by the container. Then I don’t have to have a setter that takes a String parameter, the JSTL expression, and evaluate it myself. I can just use a setter that takes an integer parameter.
- The quick, hack solution which is to get rid of the setter that takes an integer parameter. Wherever the application passes in an integer parameter, I change it to pass in a String representation of that integer.
Upgrading to JSTL 1.1
by Frank Kim on Feb.03, 2009, under JSTL
Based on this excellent post I came up with the following instructions for upgrading from JSTL 1.1.
- Update URI in JSP pages to use JSTL 1.1.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- Install in WEB-INF/lib the two JSTL 1.1 jars, standard.jar and jstl.jar. You can get these from The Jakarta Site – Standard 1.1 Taglib Downloads.
- Update the start of web.xml to look like this.
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
Do Not Return From a Try Block
by Frank Kim on Jan.29, 2009, under Java SE
In Peter Hagar’s book, Practical Java, he recommends that you do not return from a try block. This is because the finally block may change the return value.
Traditionally, programmers think that when they execute a return statement they immediately leave the method they are executing. In Java, this is no longer true with the usage of finally…
To avoid this pitfall, be sure you do not issue a return, break or continue statement inside of a try block. If you cannot avoid this, be sure the existence of a finally does not change the return value of the method. This particular problem can arise during maintenance of your code, even with careful design and implementation. Good comments and careful code reviews ward it off.
URL.equals and hashCode make blocking Internet connections
by Frank Kim on Jan.15, 2009, under Java SE
Who knew that something as innocent as java.net.URL.equals and hashCode would make blocking Internet connections?
The javadoc of URL.equals says: “Since hosts comparison requires name resolution, this operation is a blocking operation.”, but who reads the documentation of equals? There is a general contract around equals. Joshua Bloch writes in Effective Java: “Don’t write an equals that relies on unreliable resources” (Chapter 3, page 34). Hey Sun, as far as I know, the Internet is not reliable
![]()