Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Goals for the week with XDoclet, Spring and AppFuse

I have a lot that I want to accomplish this week. Hopefully a few late nights will make it possible. I'm posting this list here in case someone has already done some of this.

  • XDoclet: duplicate the Struts-specific <validationxml> Ant task for Spring. Make it work with POJOs. This is primarily motivated by the fact that I got the commons validator stuff to work just like it does with Struts.
  • XDoclet: create a new <strutsform> task that doesn't depend on ejbdoclet. This will allow me to remove AppFuse's dependency on j2ee.jar.
  • Spring: extract the mock objects used in Spring's internal test suite so I can use them to test Spring Controllers (springtestcase? ;-)).
  • AppFuse: finish Spring MVC integration and release 1.5 beta.

Phew - it's gonna be a rough week with very little sleep. Fortunately, it'll all be worth it if I can pull it off.

Update: Sometimes things just click: generate validation.xml for Spring and generate ActionForms from POJOs w/o an EJB dependency. I also discovered that <hibernatedoclet> requires that xdoclet.modules.ejb.EjbDocletTask is in the classpath. It doesn't make sense, but the compiler doesn't lie.

Posted in Java at Apr 25 2004, 04:02:15 PM MDT 3 Comments

Logout your users automatically after their session times out

One of the common issues I see in webapps is a user leaves their computer, their session times out, and when they come back to do something - the app throws errors b/c their session is null. There are several easy ways to fix this. If you use Container Managed Authentication, the user will likely be prompted to do login and can continue as before. If you're using a slick Remember Me feature (like AppFuse has), the user won't even notice. However, you might not have these options available to you. For those circumstances, I recommend you put a meta-refresh in your app to automatically show the uses a timeout message when their session expires. It's as simple as the following:

<meta http-equiv="Refresh" 
  content="${pageContext.session.maxInactiveInterval}; url=timeout.jsp"/>

I used JSP 2.0's EL in this example for simplification. If you're using a JSP 1.2 container - you'll have to wrap that expression with a <c:out> tag.

Posted in Java at Apr 24 2004, 07:33:10 AM MDT 8 Comments

Wicked Color Picker

Chris has a nice post with links to online color pickers. After looking at them, ColorMatch Remix seems to be the best one. Of course, ColorMatch's inspiration looks pretty good too.

Posted in The Web at Apr 23 2004, 09:43:24 PM MDT Add a Comment

Google Zeitgeist

Search patterns, trends, and surprises according to Google. Kinda cool.

Posted in The Web at Apr 23 2004, 11:16:29 AM MDT Add a Comment

CSS Drop Shadows

A List Apart has a new article on how to make CSS Drop Shadows that work in IE. The first article shows how to do it for all the other browsers. I dig the technique, so I've decided to use it on this site. To add it, all I did was add the following to the <head> of this page:

<style type="text/css">
    div.alpha-shadow {
        clear: both;
        float: left;
        background: url(http://www.alistapart.com/d/cssdrop2/img/shadow.gif) no-repeat bottom right;
        margin: 5px 0 0 10px;
    }
    div.alpha-shadow div {
        background: url(http://www.alistapart.com/d/cssdrop2/img/shadow2.png) no-repeat left top !important;
        background: url(http://www.alistapart.com/d/cssdrop2/img/shadow2.gif) no-repeat left top;
        float: left;
        padding: 0px 6px 6px 0px;
    }
    div.alpha-shadow img {
        background-color: #fff;
        border: 1px solid #a9a9a9;
        padding: 4px;
        margin: 0;
    }
</style>
<!--[if gte ie 5.5000]>
<link rel="stylesheet" type="text/css" href="http://www.alistapart.com/articles/cssdrop2/ie.css" />
<![endif]-->

Then I wrapped the following image with:

<div class="alpha-shadow">
  <div><img src="..." alt=""/></div>
</div>

If I decide I like this, I'll make sure and download the images/stylesheets locally so not to hog bandwidth from alistapart.com. Too bad there's not a technique to make text drop-shadows work. To see what I mean, see my Struts Resume demo. All the <h1> tags (titles) should have a drop-shadow - and they do in Mozilla, Firefox and Safari (but no go in IE).

The real question is - how do I get it to NOT float:left, but still get the drop-shadows to work? I guess I'll have to ask that question on alistapart.com.

Hmmmmm, my version doesn't work in Safari, what's up with that?!

Posted in The Web at Apr 23 2004, 07:59:47 AM MDT 8 Comments

Happy Anniversary Julie!

Today is Julie and I's 4-year anniversary. It's hard to believe that 4 years has gone by so fast. That's part of the reason I started this weblog - so I'd be able to document my life and know exactly what I was thinking on a certain date. Unfortunately, if I look back, I'll probably just see that (most of the time), a new Hibernate release came out. ;-)

I couldn't ask for a better wife or mother of my children. She really is the one for me and I couldn't be a luckier guy. Just for kicks, here's a picture on our wedding day. The funny thing is the picture is from exactly 4 years, 15 minutes ago. We got married at 5 p.m. EDT, and I suspect this picture was taken around 5:45. We'll be celebrating tonight with a babysitter and a nice dinner out.

Posted in General at Apr 22 2004, 03:59:19 PM MDT 2 Comments

Full Time vs. Contract

I talked with some folks yesterday about joining their company as a full-time employee. Their opportunity sounds awesome: using open source tools to develop a product. The opportunity certainly appeals to me. In a sense - I could get paid to work on AppFuse. I could get paid to do the stuff I wake up early and go to bed late for. I could spend more time with my family because I'm doing my "moonlighting" stuff during the daytime.

At least that was their sales pitch.

In reality, no company in their right mind is going to pay me to work on all the open source projects I contribute to: AppFuse, Roller, Struts Resume, Struts Menu and DisplayTag. Sure, they might allow me to work on AppFuse and Roller for a few hours a week, but I can guarantee that I'll still want to contribute to the others - and hence, continue to burn the midnight oil. I've also started to think that the main reason for doing stuff "after hours" is because I spend my evenings with Julie and Abbie - whereas I used to work in the evening.

More than anything, the opportunity really got me thinking about doing full-time work vs. contract work. I've been doing contract work for almost 3 years now - and I've only had 2 months of no work in that 3 year period. So that whole contracting is so unstable has been a myth for me. In fact, I see contracting as more stable than an employee position because I control my own destiny for the most part. NOTE: This post is likely a bit biased because my contract just got extended until the end of the year and I'm working on an AppFuse-based application. In other words, I love my job right now.

The thing I enjoy the most about contracting over full-time is freedom. I am planning to take 7 weeks off in the next few months (3 weeks for Spring Live, 4 weeks for the new baby) - and with a full-time gig, that would be impossible. I also like the ability (again, this is probably because my current client is so cool) to take a week off to attend a conference, or take a few days off to run off and do some training. The fact that I'm not tied down to one client/company is awesome. With the full-time opportunity I'm considering, I feel like I'd be marrying a woman I met just a few weeks ago. I guess most full-time gigs are like this after you've been set free with contracting.

One of the main reasons I'm considering this full-time gig is because I don't know where I want to be in 5 years. Most of my career aspirations have been met. When I started in this industry, I wanted to gain enough knowledge about what I do to speak at conferences and such. I did that last week and it was a blast - but I don't really want to do that every month - especially if I have to travel. Traveling away from my family is no fun - and happiness is more important than anything. The nice thing about the full-time gig is that its centered around a product, rather than services. Services (i.e. consulting) are great - but they're only good as long as I'm capable of working. Developing products that earn money while you're on vacation - that's the ideal situation.

The only thing I don't like about my current contract is that I'm a lone wolf. I'm the only guy developing the current app - which is great, but there's no "team spirit." My favorite job ever had awesome team spirit. This opportunity is a startup, which often leads to team spirit - but they also enticed me with ideas of working with a smart bunch of developers. If you've ever worked with smart people, you know that this is a real treat. Learning from your peers just by going into the office is quite a rush. When someone tries to find their answer on Google before asking you - it's refreshing. But is this worth giving up freedom for?

Another important consideration is compensation. Contracting tends to pay 50%-100% more than a full-time position. Of course, this full-time opportunity has options (which supposedly narrows the gap), but we all know that those rarely come to fruition. And if they do - it usually takes a couple of years. I am well aware that a cool job is waaayyy better than a good paying one, but still - getting paid well is nice.

Lastly, to throw a wrench into everything, someone sent me an e-mail last night suggesting they might (someday) be interested in paying me to do full-time AppFuse development. Heh - now that sounds like the ultimate dream job.

Posted in Java at Apr 21 2004, 04:53:32 PM MDT 18 Comments

Will men become obsolete?

Julie made a predication last night - men will become obsolete in 100 years. Women just won't need them anymore. On Google News today, I found this article: Males Not Needed; Mouse Born from Unfertilized Egg. Could she be right? If the world were full of women, and the male gender died off, I'm willing to bet the human race would perish shortly after from worrying so much. ;-)

Posted in General at Apr 21 2004, 12:43:15 PM MDT 3 Comments

How does your MVC framework handle duplicate posts?

One of the problems that you'll often see in webapps is that when a record is added - hitting refresh on the browser will cause a 2nd record to be added. This is because the "Save" action usually does a forward, rather than a redirect, and the full post is re-created. I'm curious to know how other MVC Frameworks handle this issue, particularly Spring, WebWork, Tapestry and JSF. In Struts, it's pretty simple to solve. When the form is first displayed, you'll likely go through an Action. In AppFuse, this would be something like UserAction.edit(). In the edit method, you add a saveToken() call to put a token into the session:

// edit method - mark start of operation
saveToken(request);

Then in the save() method, you can check for a duplicate post using the isTokenValid() method:

// save method - check for valid token
if (!isTokenValid(request)) {
    // duplicate submit, continue to success mapping
    return mapping.findForward("success");
else {
    resetToken(request);
}

How does your Java MVC framework handle this? Do you have to programmatically handle it like Struts - or is it built-in to the framework to handle it auto-magically?

Posted in Java at Apr 20 2004, 11:36:29 PM MDT 22 Comments

Performance Tuning J2EE Applications deployed on MySQL

Last week I attended Mark Matthew's "Performance Tuning J2EE Applications deployed on MySQL" at the MySQL Conference (see Anthony's Review). Mark's presentation had a lot of tips and tricks with the MySQL JDBC Driver. I asked him to send me a copy - and he did. Below are a number of tips that you might be able to use in your apps. One thing that Mark forgot to mention (he did later over beers) was that MOST apps (with less than 50 tables) won't need this stuff. You should probably only performance tune your server (or JVM) if you *really* think it's not your app or database. The database, and its indexes, is the first thing to check for slow performance.

  • To get JVM Metrics, i.e. Heap/Garbage Collection stats, add the following to your java command:
    -verbose:gc -XX:+PrintGCTimeStamps
  • The default JVM heap size is 64MB, which is likely too small for most webapps. You can change the default min/max by adding the following to your JAVA_OPTS (or CATALINA_OPTS) environment variable:
    -Xms128m -Xmx256m
  • Young generation sizing - let the JVM do it by specifying:
    -XX:+AggressiveHeap
  • Connection Pool Size: 15-20 is more than enough to handle an average application. Never have more connections than threads that can use them. For MySQL, the pool size is resource throttling, not saving connection setup time. Click here for a chart that shows the number of connections used doesn't change between a pool size of 10 and 20.
  • Connection/J 3.0 is 40-400% faster than 2.0.14 depending on the situation - use the latest driver!

Finally, here is the really good stuff. Below are a number of parameters you can add to your JDBC URL (like autoReconnect=true) to get information from MySQL's JDBC Driver:

  • Logging Slow Queries: logSlowQueries=true and slowQueryThresholdMillis=n (2000 default)
  • Reporting Performance Metrics: gatherPerfMetrics=true and reportMetricsIntervalMillis=n (30s default)
  • Usage Advisor (abandoned objects, un-used columns in selects, incomplete ResultSet traversal): useUsageAdvisor=true

Reminder: if your app doesn't have performance issues - you probably don't need to modify anything. Mark said he'd put his presentation online soon, so I won't bother doing that. I'll try to link to it when he puts it up.

Update May 25th, 2004: Mark notified me that his slides have been posted.

Posted in Java at Apr 19 2004, 08:44:25 PM MDT 2 Comments