early adopter…
March 28, 2009 on 4:18 pm | In Technical stuff | No CommentsSince I’ve been introduced to WebWork, I was a serious proponent. It was built on some interesting technologies. Implemented some great concepts. Things that are now considered standard for any self-respecting web-mvc framework. After some evolution, WebWorkis now Struts2. Since I considered myself a proponent, I’ve followed most releases. Especially the security-related items.
Recently I decided to leave the 2.0.x series, and upgrade to the 2.1.x path. After a little work, you can piece together the major changes you need to adhere. For me, the biggest change was the built-in Dojo support. As of 2.1, it’s an optional, external module, which is fine. I went about making the changes. Things like changing my theme from Ajax to XHtml. Importing the Dojo taglibs into the necessary pages. Nothing too complicated. More time-consuming than anything.
OK, so I ran into a problem. I worked at it for a good weekend. After banging my head against this one, with no resolution, I sought help on the user-list. No response. None of this really bothered me. What really bothered me was my naiveté.
The affected projects are all on svn. For some reason, I did the upgrade on HEAD. So, after no resolution, I had to revert. Since the upgrade included some other libs (Hibernate-3.3, some Commons modules, etc), I actually had to revert and then reapply some other upgrades.
Regardless of your personal feelings for a framework/library, don’t ever assume it’s going to be that easy! If you have a source control tool, use it. A branch for these upgrades would have made things a bit easier. I used to think branches were for teams larger than 2-3. Yeah, not so much. It’s not a problem to adopt a release/technology early, it’s all in how you do it. Ugh, lesson learned.
ehcache-1.6
March 15, 2009 on 1:23 pm | In Technical stuff | 3 CommentsOK, no one should have to tell an engineer to use caching. If you’re dealing with non-trivial amounts of data, and have a reasonable requirement for availability, you’ll need caching. The real issue is what, and how. The what depends on your situation. The how? Well, I’ve always thought it was obvious: ehcache. I’ve been using it as my 2nd-level cache provider for years. As cache providers go, it’s done well by me.
Well, now Greg Luck’s taking it to the next level. By moving to a minimum JDK of 1.5, he’ll be able to remove all dependencies. Also, ehcache-1.5 was a performant module. Now, if his figures are right, ehcache-1.6 will truly obliterate its peers. It’s still in beta, 1.6 that is, but check it out.
fonts and stuff…
October 1, 2008 on 8:35 pm | In Technical stuff | No CommentsEric Burke’s Blog has a post talking about finding the best font for his comics. OK, One comment brought a superior tool to light: typetester.org. Honestly, I’ve needed this thing for years.
t-mobile g1
September 23, 2008 on 8:07 pm | In Technical stuff | No CommentsFinally, if you were looking for a actual piece of hardware for your Android apps, here it goes: the T-Mobile G1. It’s not too shabby.
httpsessionlistener resolved my session persistence issue
August 19, 2008 on 9:16 am | In Technical stuff | 2 CommentsI’ve moved from Resin-3.0 to Tomcat-5.5 for a while now. So far, it’s actually been easier to deploy and run my web applications. However, I started to see some NotSerializableExceptions during shutdowns, and subsequent startups. After some research, it became clear that I was inadvertently storing Spring-proxied items into http sessions. If they still existed during serialization of the current session, Tomcat would complain, being that Tomcat actually expects truly serializable items in its sessions - how dare they
I knew the item being placed in the http session held a reference to a spring-wrapped DAO (the item’s a data view helper). So, after some cups of coffee it finally came to me: have my custom listener defined in the web.xml, which currently only implements ServletContextListener, also implement HttpSessionListener. With that, I was able clear out the culprit on sessionDestroyed(…). I wish all my technical problems were this straight forward.
Update: Anjan, in response to your question, I’m embedding the web.xml declaration and the actual Listener code. Hope this helps.
web.xml listener declaration
<!-- Our custom system initializing listener -->
<listener>
<listener-class>com.some.company.SomeInitListener</listener-class>
</listener>
Listener Implementations
public class SomeInitListener extends BosenInitListener {
private static final Logger LOG = Logger.getLogger(SomeInitListener.class);
@Override
protected void customInitForServlet(ServletContextEvent event) {
super.customInitForServlet(event);
ServletContext servletContext = event.getServletContext();
SomeResourceInitializer resourceInitializer = (SomeResourceInitializer) getBean(servletContext, "resourceInitializer");
// Make default menus
String menuConfig = servletContext.getInitParameter(AppConstants.MENU_CONFIG);
if (null != menuConfig) {
...
} else {
LOG.warn("Could not find a menu configuration.");
}
resourceInitializer.init();
}
}
public abstract class BosenInitListener implements ServletContextListener, HttpSessionListener {
private static final Logger LOG = Logger.getLogger(BosenInitListener.class);
public final void contextInitialized(final ServletContextEvent event) {
String servletContextName = event.getServletContext().getServletContextName();
if (LOG.isInfoEnabled()) {
LOG.info("Initializing [ " + servletContextName + " ]");
}
customInitForServlet(event);
if (LOG.isInfoEnabled()) {
LOG.info("Initialized [ " + servletContextName + " ]nn");
}
}
public final void contextDestroyed(final ServletContextEvent event) {
String servletContextName = event.getServletContext().getServletContextName();
if (LOG.isInfoEnabled()) {
LOG.info("Destroying [ " + servletContextName + "]");
}
customDestroyForServlet(event);
if (LOG.isInfoEnabled()) {
LOG.info("Destroyed [ " + servletContextName + "]nn");
}
}
protected void customInitForServlet(final ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
String appContextName = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
Object webCtxAttribute = servletContext.getAttribute(appContextName);
if (null != webCtxAttribute) {
if (webCtxAttribute instanceof Exception) {
LOG.error(webCtxAttribute);
}
} else {
throw new IllegalStateException("Could not read applicationContext.xml.");
}
}
protected void customDestroyForServlet(final ServletContextEvent event) {
//no-op
}
public final void sessionCreated(final HttpSessionEvent event) {
String sessionId = event.getSession().getId();
if (LOG.isDebugEnabled()) {
LOG.debug("Initializing a new Session [" + sessionId + "]");
}
customInitForSession(event);
if (LOG.isDebugEnabled()) {
LOG.debug("Initialized a new Session [" + sessionId + "]");
}
}
public final void sessionDestroyed(final HttpSessionEvent event) {
String sessionId = event.getSession().getId();
if (LOG.isDebugEnabled()) {
LOG.debug("Destroying an existing Session [" + sessionId + "]");
}
customDestroyForSession(event);
if (LOG.isDebugEnabled()) {
LOG.debug("Destroyed an existing Session [" + sessionId + "]nn");
}
}
protected void customInitForSession(final HttpSessionEvent event) {
//no-op
}
protected void customDestroyForSession(final HttpSessionEvent event) {
HttpSession session = event.getSession();
session.removeValue(BosenConstants.SESSION_PAGINATED_SEARCH_RESULTS);
session.removeAttribute(BosenConstants.SESSION_PAGINATED_SEARCH_RESULTS);
}
protected static ApplicationContext getApplicationContext(ServletContext servletContext) {
String appContextName = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
return (ApplicationContext) servletContext.getAttribute(appContextName);
}
protected static Object getBean(ServletContext servletContext, String name) {
return getApplicationContext(servletContext).getBean(name);
}
Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.
Valid XHTML and CSS. ^Top^

