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.

Struts and XHTML

There's an interesting thread over on the struts-dev mailing list. It started out debating whether to use comments (<!-- -->) or CDATA (<![CDATA[ ]]>) to hide Javascript code. I think this discussion was started by something I suggested yesterday on the struts-user list. Craig McClanahan had this to say:

What I also don't understand is why anybody is worried about generating XHTML markup for the current generation of popular browsers, none of which implement it correctly ... but that's a different issue.

What do you think? I think the best reason for generating XHTML (at this point) is that adding an XHTML doctype at the top of a page makes IE and Mozilla "snap" to standards-compliant mode. Rather than writing tweeks for each browser - the same code works in both. This is a real lifesaver when doing CSS positioning and DOM-based Javascript in pages. It's also really nice to be able to validate code.

Posted in Java at Jan 16 2003, 06:31:44 AM MST Add a Comment

Anonymous CVS taken offline at SourceForge

(2003-01-14 14:04:19) As of 2003-01-14, pserver-based CVS repository access and ViewCVS (web-based) CVS repository access have been taken offline as to stabilize CVS server performance for developers. These services will be re-enabled as soon as the underlying scalability issues have been analyzed and resolved (as soon as 2003-01-15, if possible). Additional updates will be posted to the Site Status page as they become available. Your patience is appreciated.

Posted in Java at Jan 16 2003, 06:25:13 AM MST Add a Comment

Snip Snap

I'd like to use SnipSnap to host/edit my downloads section. Write now I'm editing a plain old HTML file. I suppose I could use Roller, hmmm. I doesn't look like I can use SnipSnap on this site since it appears to only run as a standalone server, running on Jetty. I could try to run it on some crazy port or have two servers running on this site, but I prefer one.

Why do I want to use SnipSnap over Roller? For it's Wiki feature. Why don't I use a different wiki app (esp. since I did the research on them)? SnipSnap looks good - and I'm a sucker for eye candy. The rest of the wikis I reviewed are very plain. Sure I can customize them and do my own stylesheets and all that, I just don't feel like it. Who knows, maybe I will another day.

Posted in Java at Jan 15 2003, 10:12:50 PM MST 1 Comment

Java-based Forums and Free Software

I've always thought that Jive was a great product, especially when I first found it. It was free then, now it costs $450. It it worth it - yes! But it's tough to recommend this to clients when there are free alternatives. Here's one courtesy of Mathias Bogaert:

Discovered mvnForum, a JSP 1.1/Servlet 2.2 based forum application (GPL), which looks kinda neat...check out their demo.

I have this same problem at work. I told my project manager that I knew of three Bug Tracking systems: Bugzilla, JIRA and Scarab. I currently use Bugzilla for a client and I'm familiar and happy with it. I also use JIRA for Roller and XDoclet, and think it's a great piece of software. Even though I've never used Scarab, I installed it thinking that it was better than Bugzilla, and also b/c the guys from Apache are moving to it. After wrestling with the setup a bit, I got it working. Scarab's main goal seems to be ease of setup - they should take some lessons from Atlassian. Actually, we all should - I had JIRA downloaded/installed/running in under 5 minutes. Anyway, back to the point - I showed Scarab to my project manager and he went off to investigate. An hour later he came back and said he just didn't get it. I didn't have the bandwidth to investigate, and since I've never used it - we're going to use Bugzilla. I prodded and poked and tried to get JIRA; I even downloaded and installed the 30 day trial. No joy, free is what they want.

Speaking of free software, I'm inspired to do some work on Roller - especially with all the stuff that Dave and Lance have done lately. Also, my RSS feed seems to refresh old stories in Radio's aggregator, so I'm due for an upgrade. I hope to add some of the following features over the next week or so (when do we release 0.9.7?):

  • Encypted password support - both programmatically and using Tomcat's Realm. The way I've done this in the past is to create a LoginServlet that my form-based authentication maps to. This servlet does the encryption and redirects to j_security_check. I'll also include an option for an SSL-based login. Both password encryption and SSL will be off by default - and changes will be allowed in web.xml.
  • Remember Me. You're gonna love this - I sure do.
  • Remember Me in Comments. It's definitely needed if you do a lot of commenting. The question is - do you automatically do it - or allow users to say "forget me." Auto is easiest.
  • Add support for e-mailing comments and subscribing to comments when posting a comment.
  • Dig into XDoclet and make the upgrade to 1.2 Beta 2 - fixing the bug we have with Castor. I hope I'm familiar enough with how XDoclet works to make this happen. I looked through the code today and it should be working from what I can tell.
  • Upgrade to Struts 1.1 Beta 3.

Sheez! I just created a whole bunch of work for myself didn't I? Hmmm, now how do I schedule all this and get it done in a week? A late night, an early morning, a weekend? I can't decide... Oooh, here's an idea - Julie and Abbie are leaving for Florida next Thursday (I'm joining them Friday) - I could do it next Thursday night. Hopefully I can get it done sooner, but hopefully a lot of this can wait until then.

Posted in Java at Jan 15 2003, 09:47:48 PM MST 1 Comment

Conditional Task Execution with Ant

I'm trying to conditionally include my test jar files based on an Ant property. My problem is that the "if" attribute of the <task> element only accounts for the property being present or not. I'd love to be able to specify:

ant -Denable.cactus=false

But Ant seemingly executes my task if a property is present - so even though the value is false, it still executes. Any ideas? Here's my task:

<target name="copy-test-jars" depends="init" if="enable.cactus"
    description="Copy test-related JAR files to WEB-INF/lib">
    <echo>Copying Cactus, StrutsTestCase and JUnit JARs</echo>

    <mkdir dir="${webapp.target}/WEB-INF/lib"/>
    <!-- Copy jars -->
    <copy todir="${webapp.target}/WEB-INF/lib">
        <fileset dir="${strutstestcase.dir}" includes="*.jar"/>
        <fileset dir="${cactus.dir}">
            <include name="*.jar"/>
            <exclude name="commons-logging.jar"/>
            <exclude name="log4j-*.jar"/>
            <exclude name="servlet.jar"/>
        </fileset>
        <fileset dir="${env.ANT_HOME}/lib" includes="junit.jar"/>
        <fileset dir="${env.ANT_HOME}" includes="junit-noframes.xsl"/>
    </copy>
</target>

BTW, this XML was made web-savvy by the E2 Source Code Formatter - a must-have bookmark. I got this tip from The FuzzyBlog!.

Posted in Java at Jan 15 2003, 11:19:10 AM MST 6 Comments

Found: Hibernate based personal image server

I found the pixory personal image server on the hibernate-devel mailing list this morning. It looks like a regular web-based photo album, but seems to offer client side tools as well. You can checkout the screenshots if you want to get right to it.

Pixory is a personal image server based on Hibernate and HsqlDB.
-------------------------------
Pixory allows you to store your photos on your own pc but to access, compose into albums, and share them anywhere on the internet. It's your personal online photo sharing service, running on your computer using your broadband internet connection. Pixory is a client and a server, a lightweight web application for browsing photo collections on your hardrive; an album server to your friends and family or anyone on the internet. It simplifies accessing and organizing photo collections on your home network.

Today was a pretty awesome day in my development life. This morning started off great with the "remember me" feature, and I also implemented the Nested tag library from Struts. It was great - took me all of about 5 minutes to implement and get nested, indexed iterating of child objects in a form. I ended the day with disappointment as I tried to save this form. That's when I discovered that XDoclet wasn't generating getter/setters for my indexed getter/setters. I might actually have to put a form in my source tree to get this functionality. So far, all my ValidatorForms are still generated from POJOs, which Hibernate uses. Not all my POJOs are run though XDoclet -- some are generated using Hibernate's Reverse Engineering Tool. It actually seems to take less time to write the mapping file than to mark up the POJO with XDoclet tags. If you generate it with the RET, it's like taking candy from a baby.

Speaking of babies, I started to learn a new language tonight. I call it Abbie-blah - it consists of making grunts and groans and sticking your tongue out. I swear I had an intellectual conversation with Abbie - I had her smiling like you wouldn't believe. Fun times.

Posted in Java at Jan 14 2003, 09:40:12 PM MST 3 Comments

Remember Me Rocks!

I have to thank Erik for the idea of implementing "remember me" functionality. I just implemented it this morning on my current project, and it's already saving me time. I used to have to re-login each time after I re-deployed. No more, just refresh!! I love it - thanks Erik!

BTW, I ended up fixing the saving-bad-password problem by adding another cookie to the mix. This one is called authenticated and is set by my ActionFilter servlet, which filters my protected resources. Good stuff - I'll be adding it to struts-resume, and possibly Roller (is this a good feature to add?).

Posted in Java at Jan 14 2003, 09:37:29 AM MST 1 Comment

Simple Intentions turn into Remember Me Login

I woke up this morning, and had the simple intention of blogging about one of my favorite tools, The Color Schemer. If you're a wanna-be designer like me, it's awesome. It helps you match "like" colors and also allows you to select any color on your screen. It's one of my most invaluable web design tools. Putting a tip about this was my only hope at 4:30 when I sat down at this computer. Now it's 5:39.

Why am I still here? I got caught up in reading the Colorado Bloggers mailing list - which actually got some traffic yesterday. This is one of the first times I've received a message from the list. One of the members pointed me to a another Photo Album for the web. It's called Gallery and she has an example setup. Looks like it runs on PHP. Well that shouldn't have taken me an hour, right?

The activity that's filled my last hour has been wrestling with Erik Hatcher's request for "remember me" functionality in a J2EE app, using container-managed security. The good news is that I did get it working - here's how:

  1. First, I added a checkbox called "rememberMe" to my login.jsp. When the user clicks "submit", I do some JavaScript logic. This logic entails saving the username and password as cookies - but only if the rememberMe checkbox is checked. If rememberMe is checked, a cookie is set called "rememberMe" with a value of "true."
  2. Using Roller's BreadCrumbFiler (maps to /*), I added some logic to check for the existence of the "rememberMe" cookie, and if it exists, to route the user to "j_security_check?j_username="+usernameCookie+"&j_password="+passwordCookie.

This all worked fine and dandy right off the bat - took me about 10 minutes to implement. The problem was that a user couldn't "logout." So I've spent the last hour (now it's been an hour and 1/2) with my own ignorance trying to delete cookies (and doing null checks and such) so users could logout. And I just got it working - fricken sweet! What a way to start the day! The only problem I could see now is if a user tries a username/password and selects "remember me", but then closes their browser. The BreadCrumbFilter will keep trying to authenticate them - yep, I just verified that that's a problem. It's also a problem when they enter an invalid password and select rememberMe.

One way to solve this is to not set the "rememberMe" and "password" cookies until someone has successfully authenticated. Maybe I could use the breadcrumbs in the BreadCrumbFilter to check the last URL accessed, and if it's already j_security_check, don't do the routing. Anyway, here's the code that does the heavy lifting in BreadCrumbFilter:

Cookie rememberMe = RequestUtil.getCookie(request, "rememberMe");
// check to see if the user is logging out, if so, remove the
// rememberMe cookie and password Cookie
if (request.getRequestURL().indexOf("logout") != -1 && 
	(rememberMe != null)) {
    if (log.isDebugEnabled()) {
        log.debug("deleting rememberMe-related cookies");
    }

    response =
        RequestUtil.deleteCookie(response,
                                 RequestUtil.getCookie(request,
                                                       "rememberMe"));
    response =
        RequestUtil.deleteCookie(response,
                                 RequestUtil.getCookie(request,
                                                       "password"));
}

if (request.getRequestURL().indexOf("login") != -1) {
    // container is routing user to login page, check for remember me cookie
    Cookie username = RequestUtil.getCookie(request, "username");
    Cookie password = RequestUtil.getCookie(request, "password");

    if ((rememberMe != null) && (password != null)) {
        // authenticate user without displaying login page
        String route =
            "j_security_check?j_username=" +
            RequestUtils.encodeURL(username.getValue()) +
            "&j_password=" +
            RequestUtils.encodeURL(password.getValue());

        if (log.isDebugEnabled()) {
            log.debug("I remember you '" + username.getValue() +
                      "', authenticating...");
        }

        response.sendRedirect(response.encodeRedirectURL(route));

        return;
    }
}

I can post the code for RequestUtil if you need it. The class RequestUtils (for encoding URLs) is a Struts class.

Posted in Java at Jan 14 2003, 06:07:21 AM MST 4 Comments

ConvertUtils problem solved!

I got the solution to my ConvertUtils problem from the hibernate-devel mailing list. Thanks to Juozas Baliuka! Here's my new convert method:

public Object convert(Class type, Object value) {
    if (log.isDebugEnabled()) {
        log.debug("entering 'convert' method");
    }

    // for a null value, return null
    if (value == null) {
        return null;
    } else if (value.getClass().isAssignableFrom(type)) {
        return value;
    } else if (ArrayList.class.isAssignableFrom(type)
                   && (value instanceof Collection)) {
        return new ArrayList((Collection) value); // List, Set, Collection  -> ArrayList
    } else if (type.isAssignableFrom(Collection.class)
                   && (value instanceof Collection)) {
        try {
            //most of collections implement this constructor
            Constructor constructor =
                type.getConstructor(new Class[] { Collection.class });

            return constructor.newInstance(new Object[] { value });
        } catch (Exception e) {
            log.error(e);
        }
    }

    throw new ConversionException("Could not convert "
                                  + value.getClass().getName() + " to "
                                  + type.getName() + "!");
}

Posted in Java at Jan 13 2003, 09:15:09 AM MST Add a Comment

Roller gets even better with automatic linkbacks

Dave has done it again. This time, he's added automatic linkbacks to Roller - must be time to upgrade. It'll be interesting to see if a link to this post shows up on his site.

In other news, I've been struck by another annoying problem in OS X. Ever since I installed QuickTime 6.1, most of my apps crash when I try to open them. Safari and Finder are the ones giving me big problems the most. So, to recount, I'll probably be re-installing OS X for the 4th time this year. I haven't re-installed Windows this year, and I've only upgraded Linux. Keep in mind I only spend about 10% of my time in OS X. Maybe we just don't get along.

Posted in Roller at Jan 12 2003, 09:37:16 PM MST 1 Comment