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.

What a weekend...

I pulled myself out of bed and onto the keyboard with great reluctance this morning. I've been goofing off with old college buddies for the last 4 days and it's been awesome. Thursday night was my friend's rehearsal dinner and the night that folks started rolling into town. Friday night was Shane and Jodee's wedding, where I was a groomsmen and Abbie's dance partner all night. Saturday we attended a DU Hockey game with 20 other people. The score was 9-7 and it was quite a game with DU being victorious. Following the game, we verified that the DU party scene was alive and well when we met up with a bunch of "actives" from our Fraternity. We had about 10 alumni with us, so it was pretty neat meeting everyone. Yesterday was spent skiing like madmen on a beautiful day at Breckenridge. It took me two Red Bulls to drive home last night without falling asleep. What a weekend - I'm glad it's over, I'm just not that young anymore...

Posted in General at Feb 16 2004, 05:16:45 AM MST 1 Comment

Wanna use Spring in your AppFuse-derived webapp?

Yesterday, I ported an AppFuse application (based on 1.3) to use all the latest stuff I've done in the last month. Basically, I just renamed and reorganized the directory structure, integrated Spring to bind everything together, and implemented the new Remember Me functionality. If you want to upgrade your (AppFuse-derived) webapp to use Spring, I wrote up an article on how I did it. It's quite a process, but hopefully this article will make it a lot easier. Now I can use Tomcat 5 as my primary app server (vs. Tomcat 4) - sweet!

Posted in Java at Feb 13 2004, 09:40:59 AM MST 3 Comments

AppFuse Refactorings Part IV: Replacing Hibernate with iBATIS

This is a continuing series on what I'm doing to make AppFuse a better application in Winter/Spring 2004. Previous titles include: Changing the Directory Structure, Spring Integration and Remember Me refactorings.

- - - -
On my last project, we ported an existing JSP/Servlet/JDBC app to use JSP/Struts/iBATIS. In the process, I got to learn a lot about iBATIS and grew to love the framework (although I prefer to spell it iBatis). It was super easy to port the existing JDBC-based application because all of the SQL was already written (in PreparedStatements). Don't get me wrong, I think Hibernate is the better O/R Framework of the two, but iBATIS works great for existing databases. The best part is that iBATIS is just as easy to code as Hibernate is. For example, here's how to retrieve an object with Spring/Hibernate:

List users =
    getHibernateTemplate().find("from User u where u.username=?", username);

And with Spring/iBATIS, it requires a similar amount of Java code:

List users = getSqlMapTemplate().executeQueryForList("getUser", user);

The main difference between the two is that iBATIS uses SQL and Hibernate uses a mapping file. Here's the "getUser" mapped statement for iBATIS:

  <mapped-statement name="getUser" result-class="org.appfuse.model.User">
      SELECT * FROM app_user WHERE username=#username#;
  </mapped-statement>

Spring makes it super easy to configure your DAOs to use either Hibernate or iBATIS. For Hibernate DAOs, you can simply extend HibernateDaoSupport and for iBATIS DAOs you can extend SqlMapDaoSupport.

Now to the point of this post: How I replaced Hibernate with iBATIS. The first thing I had to do was write the XML/SQL mapping files for iBATIS. This was actually the hardest part - once I got the SQL statements right, everything worked. One major difference between iBATIS and Hibernate was I had to manually fetch children and manually create primary keys. For primary key generation, I took a very simple approach: doing a max(id) on the table's id and then adding 1. I suppose I could also use the RandomGUID generator - but I prefer Longs for primary keys. Hibernate is pretty slick because it allows easy mapping to children and built-in generation of primary keys. The ability to generate the mapping file with XDoclet is also a huge plus.

As far as integrating iBATIS into AppFuse, I created an installer in contrib/ibatis. If you navigate to this directory (from the command line), you can execute any of the following targets with Ant. It might not be the most robust installer (it'll create duplicates if run twice), but it seems to work good enough.

                install: installs iBatis into AppFuse
              uninstall: uninstalls iBatis from AppFuse
    uninstall-hibernate: uninstalls Hibernate from AppFuse

                   help: Print this help text.

All of these targets simply parse lib.properties, build.xml and properties.xml to add/delete iBATIS stuff or delete Hibernate stuff. They also install/remove JARs and source .java and .sql files. If you're going to run this installer, I recommend running "ant install uninstall-hibernate". Of course, you can also simply "install" it and then change the dao.type in properties.xml. This will allow you to use both Hibernate and iBATIS DAOs side-by-side. To use both Hibernate and iBATIS in an application, you could create an applicationContext-hibatis.xml file in src/dao/org/appfuse/persistence and change the dao.type to be hibatis (like that nickname ;-). In this file, you'd have to then define your transactionManager and sqlMap/sessionFactory. I tested this and it works pretty slick. Click here to see my applicationContext-hibatis.xml file.

Some things I noticed in the process of developing this:

  • Running "ant clean test-dao" with iBATIS (28 seconds) is a bit faster than Hibernate (33 seconds). I'm sure if I optimized Hibernate, I could make these numbers equal.
  • The iBATIS install is about 500K, whereas Hibernate's JARs are around 2 MB. So using iBATIS will get you a slightly faster and smaller AppFuse application, but it's a bit harder to manipulate the database on the fly. There's no way of generating the tables/columns with iBATIS. Instead it uses a table creation script - so if you add new persistent objects, you'll have to manually edit the table creation SQL.

Hibernate is still the right decision for me, but it's cool that iBATIS is an option. Even cooler is the fact that you can mix and match Hibernate and iBATIS DAOs.

Posted in Java at Feb 11 2004, 10:09:23 PM MST 10 Comments

[ANN] Spring 1.0 RC1 Released

Download or read the (rather long) set of release notes. The good thing is that all tests pass with AppFuse - so that seems like a good release to me! You can also read a condensed version of the release notes.

Posted in Java at Feb 11 2004, 05:15:33 PM MST Add a Comment

Tapestry looks very nice

Tapestry Home While leaving a comment on my ActionForms: Struts' bastard child post, Erik Hatcher sounds like a broken record:

> When are you going to just quit asking questions and try out Tapestry? 
> You can build it from CVS HEAD easily or just grab a 3.0 binary (currently 
> beta, but way stable). Drop in the WorkBench WAR file and see for yourself.

So I took 5 minutes and downloaded and deployed the WorkBench WAR. Check it out if you like. Looks pretty nice to me. The DatePicker is pretty cool, but it shows up in the wrong spot on Firefox - and it's annoying that I can't close it just by clicking on the screen somewhere (like most popup calendars). Also the Chart doesn't work on my Linux box (it worked fine on Windows).

However, if you're looking for something like the DisplayTag, Tapesty has that. The URLs it constructs for everything look a little ridiculous though. I wonder if a Filter with smarts could pretty those up?

Posted in Java at Feb 09 2004, 12:24:39 PM MST 10 Comments

[ANN] WebWork 2.0 and XWork 1.0 Released!

From the WebWork mailing list:

I'm pleased to announce the release of WebWork 2.0. You can download it
at:

https://webwork.dev.java.net/files/documents/693/2886/webwork-2.0.zip

XWork 1.0 has also been released and is available at:

https://xwork.dev.java.net/files/documents/709/2885/xwork-1.0.zip

Thank you to everyone who provided patches, support, and ideas for over
the past year to get this project from initial concept to completion. 

Congrats to all who lent a hand in getting this release out. We all know that releasing software is a great feeling - hope these guys enjoy a night or two of good sleep.

It looks like Spring 2004 is going to be a fun time - WebWork 2.0, Spring 1.0, JSF 1.0 (in March) and Tapestry 3.0 is right around the corner. It's a good time to learn a new web framework. Now if we could only get them to agree on something like their choice of expression languages and validation. ;-)

Posted in Java at Feb 08 2004, 10:32:06 PM MST 2 Comments

AppFuse Refactorings Part II: Spring Integration

I took some time last weekend and refactored AppFuse to use Spring to replace my Factories and Hibernate configuration. It only took me a couple of hours, which says a lot for Spring. I was amazed at how many things just worked. It actually lifted me out of my flu symptoms and made me feel euphoric. Or it could have been the Sudafed. In reality, I only replaced one Factory class (DAOFactory) - a fairly large class that instantiated DAOs using reflection and constructor variable inspection. I was also able to get rid of the ServiceLocator class, the getConnnection() stuff in ActionFilter and the hibernate.cfg.xml file.

The one thing I found when looking at the Petclinic and JPetstore apps was that they used an applicationContext.xml file for unit tests, and a (very similar) one for running the app in a container. To me, this was a warning sign. DRY (Don't Repeat Yourself) is a big reason for using XDoclet and I'm beginning to think that Spring could benefit from a little XDoclet lovin'. Anyway, back to the story.

I wanted to find a way to use the same XML files for testing and in-container execution. As you might know from Part I, AppFuse has 3 different tiers: dao, service and web. To run unit tests for the dao and service layers, I simply load a applicationContext.xml file in my JUnit test's setUp() method and go from there. I saw this in the petclinic app and found that it works pretty well. In the end, I decided to setup different XML files for each layer - applicationContext-hibernate.xml, applicationContext-service.xml and applicationContext.xml for the web layer. The main applicationContext.xml uses entity includes to reference the other two files.

The main pain I found was that the entity includes required different paths for tests vs. running in container. Basically, for tests, I had to use:

<!ENTITY database SYSTEM "applicationContext-database.xml">

While tests, using the ClassPathXmlApplicationContext required:

<!ENTITY database SYSTEM "WEB-INF/applicationContext-database.xml">

Using Ant to do a little replace logic allowed me to jump over this hurdle.

Using this setup, any new DAO definitions are added in src/dao/org/appfuse/persistence/hibernate/applicationContext-hibernate.xml, new Manager definitions (and declarative transaction settings) are be added in /src/service/org/appfuse/service/applicationContext-service.xml. The test-specific applicationContext-database.xml sits in the "test" directory and contains the following:

<bean id="propertyConfigurer" 
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
	<property name="location"><value>database.properties</value></property> 
</bean> 

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
	<property name="driverClassName"> 
		<value>${hibernate.connection.driver_class}</value> 
	</property> 
	<property name="url"> 
		<value>${hibernate.connection.url}</value> 
	</property> 
	<property name="username"> 
		<value>${hibernate.connection.username}</value> 
	</property> 
	<property name="password"> 
		<value>${hibernate.connection.password}</value> 
	</property> 
</bean>

While the applicationContext-database.xml for the web is simply:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName"><value>jdbc/appfuse</value></property>
</bean>

To integrate Spring with my web layer (Struts), I just used the ContextLoaderListener in my web.xml file. I didn't see any point in bringing yet another JAR file into the mix.

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Finally, to expose Spring's context to my Struts Actions, I added the following to my BaseAction.java class:

    private WebApplicationContext ctx = null;

    public Object getBean(String name) {
        if (ctx == null) {
            ctx = WebApplicationContextUtils
                  .getRequiredWebApplicationContext(servlet.getServletContext());
        }
        return ctx.getBean(name);
    }

This way, the UserManager implementation can be easier retrieved using:

    UserManager userMgr = (UserManagergetBean("userManager");

The best part about the Spring integration in AppFuse is: (IMO) its Hibernate support and how it drastically simplifies my Hibernate DAOs (as if Hibernate wasn't simple enough already). I dig the ability to specify declarative transactions, and this refactoring seems to have reduced the "src" distribution of AppFuse by 2 MB (to 10MB total)! I don't know where this came from since the Spring JAR is almost 1 MB. The appfuse.war is about 500 KB larger, but I can live with that.

Of course, all of this has been checked into CVS if you'd like to take a look.

Posted in Java at Feb 05 2004, 12:52:18 PM MST 17 Comments

How much CPU Power does a Java/Tomcat app need?

I tried posting the following to the tomcat-user list, but after not seeing it show up for 2 days, I'll just try it here.
----

I have developed a webapp that uses basic open source stuff (struts, hibernate,
etc.).  I've been developing/testing it on the following platforms - where it
works fine and runs lickedy-split:

OS X 10.3, 1.33 GHz, 1 GB RAM
Windows XP, 2.6 GHz, 1.5 GB RAM
Windows 2000 Server, 1 GHz, 512 MB RAM
Windows 2000 Server, 1.5 GHz, 256 MB RAM

All of these are running Tomcat 4.1.29 or 4.1.12.  I recently tried to deploy
it to the "test web server" (Windows 2000 Server) at my client and it runs 
dreadfully slow.  It takes almost 30 seconds to load a page.  The main difference
is that the test web server has a 667 MHz CPU.  It has 512 MB RAM, and we 
upgraded it to 1 GB, but that didn't help at all.  

I've recommended we get a faster CPU for the test web server, but I wanted to
confirm that this could be the source of the problem.  On this server, and the
1.5 GHz/256 MB RAM machine, IIS is integrated with Tomcat.  All machines are
running JDK 1.4.0 or above.

Any help is appreciated.

Posted in Java at Feb 05 2004, 07:38:05 AM MST 13 Comments

ActionForms: Struts' bastard child

Folks that rag on Struts seem to point to ActionForms as one of its major design flaws. I've been slightly frustrated with ActionForms this week, but overall, I think they're a good thing. It's possible my ActionForm affection is misguided. The major reasons I like them is because I believe they allow me to do stuff that is not possible in other web frameworks. I definitely could be wrong though, so I'm hoping the other framework authors/users will speak up and say "My framework does that!" Specifically, I'm talking to the WebWork, Tapestry, JSF and Spring folks.

I do wish that I could throw my POJOs up to my UI, so I hope the following things are possible with the WTJS frameworks. It would simplify things if I didn't need to transform POJOs -> ActionForms (particularly with Hibernate).

  • Validation and re-displaying the user's entered values. I love Struts' Validator. It's great how I can generate the validation.xml file with XDoclet and have a "required" struts.validator tag right next to a hibernate not-null="true" tag. Two questions:

    1. Can any of the WTJS frameworks re-display the user's entered values? Specifically, back into the input fields where the user entered them? I think this is important for useability.

    2. Do any of them have the ability to generate client and server-side validation, or at least declaratively write it in XML?

    I'd love to find a way to hack the Validator to allow you to define validation rules for a POJO and then use an Interceptor to validate it. I don't like how Spring requires you to write YAJC (Yet Another Java Class) to do validation.
  • Handling checkboxes. The basic reason for the reset() method in ActionForms is to handle checkboxes. Since unchecked checkboxes don't send a value - there needs to be a way to set a boolean back to null. I'm sure all of the WTJS frameworks support checkbox handling, I just want to make sure - and frankly - I'd like to learn a little more about how each framework handles it.

I guess there's only two reasons I like ActionForms - the major one being the ability to specify (and generate) my client and server-side validation in XML. If I don't find this same slick feature in the other frameworks, I might have to do a bit of hacking to do the Interceptor with Validator thing - but hopefully I won't need to go there.

Posted in Java at Feb 04 2004, 08:31:13 PM MST 25 Comments

Approved for Google Ads

After seeing that Tim Bray is making $500/month of Google Ads, I decided it was high time I try to get this site approved again. Low and behold it worked! So they've approved me, but I only want to show them when folks come from Google. As in, when the referer (yeah, I know that's spelled wrong, but it is in Java and JavaScript too) contains "google" - show the ads. Anyone know how to do this cleanly in Roller/Velocity? Or JavaScript? I tried the following, but it doesn't work:

if (document.referer != null 
    && document.referer.toString().indexOf("google") != -1) {
    // define variables
    document.write("<scr" + "ipt type='text/javascript' src='ads.js'><\/scr" + "ipt>");
}

Since Google is my top referrer - I think I'll get a fair amount of users seeing the ads, and it won't disturb the folks who come here just to read my ramblings.

Posted in Roller at Feb 03 2004, 08:10:33 PM MST 10 Comments