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.
You searched this site for "young russian teenboy model pre teen". 788 entries found.

You can also try this same search on Google.

Prevent Caching of JavaScript and CSS files

We've been having an issue at work for awhile now where our .css and .js files are cached by a proxy server. When we update the app, we get a few users (behind the proxy server) that get served up an old style/script file, and the app looks like it's broken. So I added a super-simple cache-killer to our .js and .css files today. In my taglibs.jsp (included in every JSP), I added:

<%-- Create a variable that is the current time (in milliseconds) to kill
     caching on the proxy server --%>
<jsp:useBean id="now" class="java.util.Date" />
<c:set var="cacheKiller">
    <fmt:formatDate value="${now}" pattern="yyyyMMdd"/>
</c:set>

My date pattern only goes to the day because we don't update the site more than once in the same day. This way, the users will still get the stylesheet/script caching benefit of the browser, but now we control when the file is reloaded, rather than the proxy server. To make sure these files are re-fetched every request, you could use pattern="yyyyMMddHHmmssS" to get all the way down to the millisecond. After adding this, I adjusted my baseLayout.jsp (Tiles template) to add my cacheKiller as a parameter to the src attributes of scripts and stylesheets.

<%-- Get Javascript List --%>
<tiles:useAttribute name="scripts" ignore="true"/>

<c:forEach var="js" items="${scripts}">
    <script type="text/javascript"
        src="<html-el:rewrite page="${js}"/>?<c:out
             value="${cacheKiller}"/>"></script>
</c:forEach>

Works like a charm!

Posted in Java at Jul 14 2003, 10:16:48 AM MDT 6 Comments

Added "Comment" link to RSS Feed

Thanks to Lance, my RSS feed validates once again. [Details]. Also, I added a "Comment" link to the bottom of my posts (in the RSS feed). I got the idea from Russ and I think it's a good one. In my rss.vm file, I changed:

<content:encoded><![CDATA[#showEntryText($entry)</content:encoded>

To:

<content:encoded><![CDATA[#showEntryText($entry)
#if( $website.AllowComments )
   <p align="right"> 
   <a href="$absBaseURL/page/$entry.website.user.userName?
               anchor=$entry.anchor">Add a Comment</a>
   </p>   
#end]]>
</content:encoded>

In the code above, the href should all be one one line, but in order to get NetNewsWire to render my full post, I had to split it up. Is this a bug? It seems if I have a <pre> with too many characters (>80?), then it just ends the post.

If Roller users dig this enhancement, I'll commit it to CVS.

Posted in Roller at Jul 11 2003, 10:25:19 AM MDT 1 Comment

Compression Filter Issues - EOFException

I'm having some issues with implementing a Compression Filter in my day-time project. It works fine via the browser (and in AppFuse/Roller), but not in one of my Webtests. I think this is because my response doesn't have anything in it, but who knows. From my log file:

CompressionFilter.doFilter(87) | Unzipped size: 0
CompressionFilter.doFilter(106) | Zipped size: 20

And then the lovely error message from my testcase:

[canoo] java.io.EOFException
[canoo]     at java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:200)
[canoo]     at java.util.zip.GZIPInputStream.readUShort(GZIPInputStream.java:190)
[canoo]     at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:130)
[canoo]     at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:58)
[canoo]     at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:68)
[canoo]     at com.meterware.httpunit.WebResponse.defineRawInputStream(WebResponse.java:617)

I'm thinking I need to close a stream or something, but since it works fine via the browser - I'm stumped! Any ideas are appreciated. I can post the testcase if necessary.

Update: Richard Hill on the Webtest mailing list hooked me up with the solution. It turned out to be a bug in the JDK, which causes issues in HttpUnit. Here's the solution I used to workaround it.

Posted in Java at Jul 10 2003, 04:59:51 PM MDT 2 Comments

Changing Struts' bean:message to JSTL's fmt:message

I converted AppFuse to use JSTL's <fmt:message> tag instead of Struts' <bean:message> tags this morning. It was pretty easy. Here's the steps I took:

1. First, I added the following to metadata/web/seb-settings.xml:

<!-- Define the basename for a resource bundle for I18N -->
<context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>ApplicationResources</param-value>
</context-param>

2. Then I added the format tag to web/common/taglibs.jsp:

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

3. Finally, I did find/replace with <bean:message/<fmt:message.

4. I also had to change my title and header keys in web/WEB-INF/tiles-config.xml to remove the . from the bean names. In other words, I converted title.key and heading.key to titleKey and headingKey and also made the appropriate changes in web/layouts/baseLayout.jsp.

Easy as Pie!

Posted in Java at Jul 10 2003, 07:59:29 AM MDT 35 Comments

[Denver JUG] The J2EE 1.4 Web Foundation: Servlets and JSPs

I'm sitting in the Qwest Auditorium right now, in the heart of downtown Denver. It's 7:20 p.m. and Sue Spielman is getting ready to launch her presentation on J2EE 1.4. There is a gentleman who is trying to start a JBoss Special Interest Group - if you live in Denver and are interested - send an e-mail to the DJUG mailing list. I've been here since 5:45 (after driving an hour from DTC) so this better be good. ;-) The Eclipse in Action speaker (David Gallardo) is coming to speak in October. In September, the author of AspectJ is coming in conjunction with Grady Booch. Never heard of him, but judging from the applause - I'm living under a rock.

On with the presentation. Sue thinks that J2EE 1.4 will be released towards the end of this year. Damn, I was hoping for the end of the summer.

What's new in Servlets 2.4?

1. Platform Requirements:

  • HTTP/1.1 - New static constants. HttpServletResponse.SC_FOUND to represent status code 302 instead of HttpSerlvetResponse.SC_MOVED_TEMPORARILY.
  • J2SE 1.3

2. DTD to XML Schemas:

  • Provides easier way to define element structure, element ordering structure is arbitrary under <web-app>
  • New elements in 2.4 XSD: <env-entry>, <resource-ref>, <resource-env-ref>, <jsp-config>

3. Complete event listener lifecycle:

  • New Request Events. Be aware that distributed containers handle listeners a bit different (1 instance per JVM).
    • ServletContext - manage, startup/shutdown, attribute changes
    • HttpSession - creation, invalidation, attribute changes, migration if sessions distributed
    • Request - request coming in or out of scope in a web component, attribute changes
  • javax.servlet.ServletRequestEvent, ServletRequestAttributeEvent
  • new interfaces ServletRequestListener, ServletRequestAttributeListener
  • SessionActivationListener is what you'd use for serializing sessions across a cluster

4. Filter enhancements:

  • Ability to configure filters to be invoked under request dispatcher. What does "under the Request Dispatcher mean?" It means that you can apply filters under RequestDispatcher forward() and include() calls. Defined in web.xml:
  • <dispatcher>REQUEST</dispatcher> and/or FORWARD, INCLUDE, ERROR (REQUEST was the only option in Servlets 2.3)
  • Example: if you have INCLUDE - a request doesn't invoke the filter, a forward doesn't invoke the filter, but an include would.

5. Enhancements for i18n:

  • Two new methods: setCharacterEncoding(String encoding) - do before getWriter() and getContentType().
  • <locale-encoding-mapping-list> - new element in the XSD to provide the deployer with the ability to assign locale-to-charset mappings outside servlet code.
<locale-encoding-mapping>
  <locale>en</locale>
  <encoding>en_US</encoding>
</locale-encoding-mapping>
  • Response encoding for English locales will default to US English (as opposed to the "other" English from Great Britain) ;-)

6. API Improvements added to the ServletRequest to help handle proxy servers: getLocalAddr(), getLocalName(), getLocalPort(), getRemotePort().

7. Other improvements:

  • Distributed sessions must throw an IllegalArgumentException if an object placed in the session can't be serialized
  • Relationship b/w session invalidate/timeout clarified (can now set zero or negative values in <session-timeout>)
  • Deprecation of Single ThreadModel (never used it - did you?)

8. Misc. Clarifications:

  • Welcome files can be servlets
  • Any library files exposed by the container apart from the WEB-INF structure must be loaded by the same classloader w/in any single JVM.
    • Examples include the JARs Tomcat loads from $CATALINA_HOME/shared/lib
    • This should help in avoiding potential ClassCastExceptions

As I expected, there still is now way to get the user's requested URL with container managed authentication. Damn.


JSP 2.0

1. Simplifies tag extension protocol

  • SimpleTag interface: doTag(), Tag attribute methods, NO scriplet code allowed
  • SimpleTagSupport class, implements SimpleTag, adds convenience methods: public JspFragment getJspBody(), public JspTag getParentTag()

2. Relationships: .tag file mechanism allows page authors to use JSP syntax to write custom actions

  • Use directive standard syntax: <%@ tag %> instead of <%@ page %>
  • JSP compiler generates custom action code (look in Tomcat's work directory)
  • Flexible packaging:
    • drop .tag file into WEB-INF/tags
    • implicit tag library generation
    • can still write a TLD if you want, or TLD in a JAR file

3. EL Functions: simple function invocations, defined in tag libraries, but it's a fair amount of work - like writing a TLD file and .java source file.

4. Expression Language:

  • . and [] operations access JavaBean properties and Collection elements
  • ${books.title}, ${books[title]}, ${books["JSTL Practical Guide"]}
  • Automatic type conversion
  • Ability to specify defaults (i.e. in case of null)
  • EL can access Cookies, request params, headers, scope variables and others

5. XML-based JSPs:

  • .jspx and .tagx for pure XML versions
  • no more <jsp:root> just use namespace: xmlns:jsp=http://www.sun.com/JSP/Page
  • For full list of XML features - see section 6.

JSTL (Java Standard Tag Library)

  • Over 42 standard custom actions available for common tasks needed by page authors
  • JSTL will become rev 1.1 in the J2EE 1.4 release

1. Core features:

  • Control flow: for each, conditionals
  • URL management: encoding, ftp, http
  • Formatting and i18n: date, time, numbers, locales
  • XML: transformations and XPath
  • Database support: queries, data sources, transactions
  • 4 custom action libraries: core, xml, i18n formatting, sql.

Man, Sue really knows her stuff. This was a very enjoyable presentation for me and I'm glad I came. Too bad JSPs can't be used as templates like Velocity - that would be sweet! Of course, I like Velocity and it is easy to use - but I've never implemented it from scratch. I do hope to in Moblogger and Struts Menu, but who knows when that will happen.

Update (7/17/2003): Presentation slides from this are now available for download:

  • July 9 - Basic Concepts: Scott Davis Apache Xerces - XML Parse (PowerPoint and samples)
  • July 9 - Main Speaker: Sue Spielman J2EE 1.4 Web Foundation (PowerPoint)

Posted in Java at Jul 09 2003, 11:15:44 PM MDT Add a Comment

Search improvements and HowTo set your title

I did some re-factoring to the Google search box for this theme, and also figured out a slick trick to set your weblog's title to be == $lastPost.title. Basically, I refactored my _day template to add the search box when building the page, rather than after the fact.

You ask "why, I thought you loved the DOM?" I do, but it was giving me some strange behavior: in IE, a "entry" bar would show up in the middle of the last post (fixed by scrolling) and in Mozilla Firebird, I was getting a slight "shift-left 10px" behavior of the whole page. So I built it with Velocity, here's how. In my _day template, I changed this:

<div class="entry">
   #showDayPermalink( $day )
   #showEntryDate( $day )
</div>

To this:


<div class="entry">
#if ($velocityCount == 1) 
  <div id="search" style="float: right; margin-top: -2px">
    <form id="searchForm" method="get" onsubmit="return search()"
        action="http://www.google.com/search"
        style="margin: 0; padding: 0">  
        <input type="text" id="q" name="q" size="20" 
            maxlength="255" value="search this site" 
            style="font-size: 11px; border: 1px inset silver; 
                   font-weight: normal; padding-left: 2px"
            onclick="this.value=''" /> 
    </form>
  <script type="text/javascript">
    function search() {
        form = document.getElementById("searchForm");
        if (form.q.value == "search this site" || form.q.value == "") {
            alert("Please enter a search term to continue.");
            form.q.focus();
            return false;
        } else {
            form.q.value = form.q.value + " site:www.raibledesigns.com";
            form.submit();
        }
    }
    document.title="Raible Designs ~ $entries.get(0).title";
  </script>
  </div>
#end
   #showDayPermalink( $day )
   #showEntryDate( $day )
</div>

There's also a hint in there to set your weblog's title to match the title of your last post. Enjoy!

Posted in Roller at Jul 01 2003, 02:46:22 PM MDT Add a Comment

[ANNOUNCE] Struts 1.1 Final Released!

The Struts team is proud, and extremely pleased, to announce the Final release of Struts 1.1. This release includes significant new functionality, as well as numerous fixes for bugs which were reported against the previous release, and supersedes the earlier 1.0.2 version as the latest official release of Struts from the Apache Software Foundation.

Download Binary | Download Source | JARs Only | Release Notes

test-all:                                                                                                               
                                                                                                                        
BUILD SUCCESSFUL                                                                                                        
Total time: 8 minutes 10 seconds                                                                                        
[minime:~/projects/appfuse] matt%   

Results look good!

Posted in Java at Jun 30 2003, 06:17:31 AM MDT Add a Comment

Added Google search to this theme

The idea hit me like a cold beer pouring down my throat on a hot summer day. Crisp, clean and exciting. I've been wanting to add a search form to this theme, but I didn't want to add another tab, and putting it anywhere in the header would conflict with the background image. And then I spotted the perfect spot. Right under the categories, in the banner of the first entry on this page. With a little love from the DOM, you can now search this site using this theme and Google. Here's the relevant code that I added to the bottom of this theme.

<div id="search" style="display:none; margin-top: -17px; text-align: right">
    <form id="searchForm" method="get" action="http://www.google.com/search"
        onsubmit="return search()" style="margin: 0; padding: 0">  
        <input type="text" id="q" name="q" size="20" maxlength="255"
            value="search this site" onclick="this.value=''" /> 
</div>
<script type="text/javascript">
    // get the first entry shown in the page and append the
    // hidden 'search' div from above
    document.getElementById("entries")
            .getElementsByTagName("div")[0]
            .appendChild(document.getElementById("search"));
    toggle("search");
    function search() {
        form = document.getElementById("searchForm");
        if (form.q.value == "search this site" || form.q.value == "") {
            alert("Please enter a search term to continue.");
            form.q.focus();
            return false;
        } else {
            form.q.value = form.q.value + " site:www.raibledesigns.com";
            form.submit();
        }
    }
</script>

Boy oh boy does the DOM make it easy to do web sites! Seems to work in all the browsers I use regularly (IE/Moz on Win, Camino/Safari on Mac). It doesn't work in Opera 6, but does in Opera 7. Now back to that cold beer - I'm gettin' thirsty...

Posted in Roller at Jun 27 2003, 04:57:58 PM MDT 8 Comments

Added Calendar to Menu

I added a calendar to my "badges" menu on the top left. This is a JavaScript-based calendar that I obtained from Matt Kruse's JavaScript Toolbox. I don't know if I'm satisfied with the green background on the "cal" image, but it'll have to do for now. I've noticed a couple of issues in Safari (too far down and too the right, and doesn't go away like it should), but it seems to work pretty good in IE/Mozilla. I tried disabling dates > today, but couldn't get it to work (yeah, I tried the code from Matt's site).

I don't know if it's worth the effort of talking to Roller's CalendarModel to get the actual days that somethings been posted. However, it would probably be fairly easy to generate a JavaScript array for the current month, rather than an HTML-based <table>.

If you're interested, here's how you can add this sucker to your Roller weblog:

1. Add the following code to the <head> of your template.

    <script type="text/javascript" src="pathToScript.js"></script>
    <script type="text/javascript">
        var cal = new CalendarPopup("calDiv");
        cal.setReturnFunction("showDate");

        document.write(cal.getStyles());
            
        // Function to get input back from calendar popup              
        function showDate(y,m,d) {
            var day = y+LZ(m)+LZ(d);
            location.href = "$ctxPath/page/$userName/" + day;
        }
    </script>

2. Add an empty, invisible div anywhere w/in the <body> of your template (I put mine at the bottom).

<div id="calDiv" 
    style="position: absolute; visibility: hidden"></div>

3. Add a link (can contain an image) to invoke the calendar popup.

<a href="?" name="calAnchor" id="calAnchor" 
    onclick="cal.showCalendar(this.id); return false">
    Calendar</a>

You can download the calendar.js file from this site, but please don't link to it - I have enough bandwidth problems as is (and I'm going to move it to a new theme name). Enjoy!

Posted in General at Jun 25 2003, 09:49:49 PM MDT 2 Comments

Struts 1.1 Final ~ might be released on Sunday

According to the struts-user mailing list, the Struts Dev Team is going to try and release 1.1 Final this weekend! Sweet!

From: Ted Husted
Subject: Re: [ANNOUNCEMENT] Struts 1.1 Release Candidate 2 released
Date: Wed, 25 Jun 2003 03:30:47 -0700 
-------------------------------------

Just a note on the RC2 status.

Martin posted the release vote for FileUpload on Monday, and there
are already 3 binding +1s. <yeah!/>

We've one outstanding Bugzilla ticket against RC2, which we should 
be able to either resolve or postpone. Given the imminent release 
of FU 1.0, I plan to post the Struts 1.1 Final Release vote 
tomorrow, so that we can roll it out on June 29. <double-yeah!/>

-Ted.

This doesn't mean much to me since the current RC2 release works fine for me (if I didn't, I'd use a nightly). However, it's cool that this is finally being released. It's too bad it took so long - such is the nature of open source - I probably won't release struts-resume 1.0 until 2004. And who knows when Roller 1.0 will be released...

Posted in Java at Jun 25 2003, 08:34:10 AM MDT Add a Comment