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 "ant". 338 entries found.

You can also try this same search on Google.

Rename Packages Tool for AppFuse

One of the steps recommended in AppFuse's QuickStart Guide is to rename your project's packages from "org.appfuse" to "com.company.appname". In the past this has been a real pain. I recommended using Eclipse, but this only worked for renaming the .java files themselves. It didn't catch all the package names in .xml and .properties files. Furthermore, it did nothing to change any references to "org/appfuse/model" or any other similar paths.

No longer folks. Ben Gill has developed a "rename packages" Ant task that'll zip through your AppFuse project and rename everything for you!

To use it, simply download it and view the README file to install and use. The source for this project is also available. This tool should work regardless of whether you've installed any options or not. Thanks Ben!

BTW, I should mention there will be an AppFuse 1.6.1. There have been a few bugs entered and fixed in 1.6 and I'd like to add support for Tomcat 5.5.3 (now in Cargo's SVN) and upgrade to XDoclet 1.2.2 (due for release soon). I'll probably wait until there's both Cargo and XDoclet have been released - in case some more bugs trickle in.

Posted in Java at Oct 13 2004, 11:09:12 AM MDT 1 Comment

Resin slower than Tomcat, fails the AppFuse Test

As part of AppFuse 1.6, I was hoping to supply the option to use Resin instead of Tomcat. In reality, hardly anyone has asked for this on the mailing list - but since so many folks say that "Resin is better" - I figured I'd give it a whirl. I hate to be the guy that spoils all the Resin users mantra, but it seems like Tomcat is the better server. Why? Speed, compliance and shit works. Here are some things I found:

  • Server startup time when AppFuse is only app installed (deleted work directories before starting):
    • Resin: 25 seconds
    • Tomcat: 14 seconds
    I also found that Resin loads my StartupListener twice b/c it's defined in web.xml and XDoclet puts it in the generated TLD. I think the best solution is to add a flag to XDoclet to allow you to exclude listeners from the TLD when it's generated. I commented out the entry in web.xml for this test.
  • Running "ant test-canoo" which runs through all the JSPs using Canoo's WebTest (server already started):
    • Resin: 1st run (no compiled JSPs) - 53 seconds, 2nd run (compiled JSPs) - 24 seconds.
    • Tomcat: 1st run (no compiled JSPs) - 49 seconds, 2nd run (compiled JSPs) - 14 seconds.

I did have to hack a number of things to even run the tests (which verifies titles, success messages, etc.) on Resin. First of all, SiteMesh seems to puke with if you try to use <dispatcher>FORWARD</dispatcher> on the filter-mapping. I had to comment this out, resulting in a lots of HTML Tidy errors during the tests ( Error: <content> is not recognized!). I also had to turn off Resin's fast-jstl to bypass this bug. Finally, I had to revert the displaytag to using the non-EL version (which required changing titleKey -> title and name="${listName}" -> name="listName"). It seems that Resin enables EL even if you're using a 2.3 DTD. With Tomcat, and I believe the spec says this, EL is only enabled if you use a 2.4 XSD.

So there you have it folks, not only is Resin 3.0.9 slower than Tomcat 5.0.28 (JDK 1.4.2, Windows XP), but it's not standards compliant. Of course, the speed could be due to my using the open source version (with performance enhancements turned off) - but I'd think the other (albeit minor) stuff should be easy to fix. Everytime I try to use Resin, I end up finding bugs and going back to Tomcat. I guess this is another one of those days. I don't think I'll include a Resin installer as part of 1.6, but I might distribute one later if I can get these issues solved. I wonder if I should give Orion a run for its money?

P.S. Since I know people are going to ask: Tomcat 5.5.3 with JDK 5.0 took 9 seconds to startup. Running "test-canoo"? First run: 37 seconds, second: 14 seconds. Looks like the new compiler is quite a bit faster.

Posted in Java at Oct 07 2004, 07:13:09 PM MDT 24 Comments

Aren't out-of-container tests supposed to be faster?

Earlier this week, I converted my StrutsTestCase tests from using CactusStrutsTestCase to MockStrutsTestCase. At first, this seemed like a great thing - on my Windows XP box. To run all the tests in AppFuse, it takes around 2:20. I know, this is quite a bit of time for unit tests - but it was 3:15 in version 1.5. At least it's faster than it was. 1:20 of this is for starting Tomcat and running Canoo WebTests.

This all seemed great until I ran "ant test-all" on my PowerBook tonight. It averages around 7:00 minutes. WFT?! I know PowerBooks are slow - but they're not that slow. I'm guessing the reason is because Spring's ApplicationContext is loaded by each test - whereas the Cactus versions would always grab it out of the ServletContext. Sounds like I need a TestSuite.

What if I isolate and compare times for just the "test-web" target? This target runs all the Action, Filter and Listener tests. Time to execute on Windows: 33 seconds, PowerBook: 2 minutes 21 seconds. What about just testing the JSPs (with Cargo)? Windows: 1:24, PowerBook: 3:32. My Windows desktop has 1.5 GB RAM and a 2.6 GHz processor. My PowerBook has 1 GB RAM and 1.5 GHz. I agree that it seems like an unfair comparison - but AppFuse tests ran in around 4 minutes on the PowerBook in the last release. I guess it's back to the drawing board.

Update: Nevermind. I just downloaded and checked out AppFuse 1.5 - almost 8 minutes for running all the tests. If I were going to work on my PowerBook for my next project, I'd refactor AppFuse Managers and Actions to use jMock. Luckily I'm using my Windows machine. ;-)

Update 2: I found a solution! Using Ant 1.6.2's forkmode="once", I was able to reduce the time of the test-web target from 2:21 to 24 seconds on my PowerBook!! Windows: :33 -> :18. Running "ant test-all" on the Mac is now 2:15 - while the Windows version is 2:20.

WTF!? My PowerBook is actually faster than my Windows box? I never thought I'd see the day - Yeeee haaawwww!!

Now I just have to figure out how to detect 1.6.2 and warn users if they aren't using it.

Posted in Java at Oct 05 2004, 09:26:56 PM MDT 8 Comments

Resin now Open Source?

I noticed on the release notes for Resin 3.0.9 (released last Saturday) that they now have an open source (GPL) version.

Resin Open Source (GPL) - Contains all functional components of Resin, including EJB, but excludes performance and clustering capabilities.

Excludes performance capabilities? What does that mean - is it slow on purpose? ;-)

I was planning on looking at AppFuse on Resin again tonight and hopefully figure out a way to make it easy to setup/test/deploy on Resin instead of Tomcat. Since AppFuse currently works fine on Resin, this shouldn't be too hard. The hard part is going to be finding a non-obtrusive way to setup Resin.

With Tomcat, I can copy a couple JARs to $CATALINA_HOME/common/lib and an appfuse.xml file to $CATALINA_HOME/conf/Catalina/localhost and the app is setup and ready to go. Better yet, I can use Tomcat's Ant tasks to deploy a WAR with an embedded context.xml file and it'll get copied to the appropriate location.

Is there a similar system that Resin allows? I know I can do the copy-JAR thing. However, the last time I checked, you had to manually edit the resin.conf file to import a <web-app> definition.

Posted in Java at Oct 05 2004, 04:03:36 PM MDT 7 Comments

Integrating WebWork into AppFuse

Last week was a busy one as I was trying to finish up AppFuse 1.6 before starting my new gig (more on that later). Most of this involved 1) integrating WebWork and 2) writing the Ant-based installer for replacing Struts with WebWork. I've worked with WebWork before, so this post is mostly an extension of that - as well as documentation on what I did so others can understand AppFuse+WebWork better. Below is a list of things I found.

  • WebWork's concept of "results" are very similar to Struts "action-forwards". However, they also allow you to chain to other actions and use expressions.
  • Implementing the ModelDriven interface in your Actions is a good idea, but it's not that great. I found that by simply using get/setUser(), I got the same functionality - except that I had to add "user." to all my form elements in my JSP. The advantage to doing things this way (over ModelDriven) is you can have an Action that services many objects. The main reason I'm not using ModelDriven is because the following tag doesn't render the label (it's just blank). Strangely enough, it renders just fine after validation fails.
    <ww:textfield label="getText('user.firstName')" name="'user.firstName'"
        value="user.firstName" required="true"/>
  • WebWork is similar to Tapestry in that they encourage you to specify i18n messages (properties files) on a per-action basis (Tapestry is per page). Some might think this is a good idea, but after using Struts and Spring, I'm used to using one ResourceBundle for everything. To migrate AppFuse from using 1 bundle to many bundles just for WebWork would've been a pain. Luckily, in WebWork 2.1, they added the ability to specify a custom bundle using "webwork.custom.i18n.resources=ApplicationResources" in webwork.properties. I believe my issue with ModelDriven and labels is caused by this new feature.
  • The Spring-integration provided by SpringObjectFactory is quite nice. Unfortunately, client-side visitor validation doesn't work with it.
  • Unit-testing WebWork actions is easy, though it's kinda wierd to not send request parameters and such to set values (instead, you just set values directly on the Action).
  • I experimented with putting stuff on the stack and pulling it off in JSPs, but never got it to work quite right. After failing the 10 minute test, I decided to just put stuff in the request and get it working. Looking through the code now, there's only 3 places where I'm stuffing attributes into the request: 2 in FileUploadAction and 1 in ExceptionHandlerInterceptor.
  • With most frameworks I've used in the past, I rarely jumped into the source to try and see how things worked. Because of this, I rarely extended framework classes for my own use. However, with WebWork/XWork, I found it quite easy to dig in and extend the framework. Especially with Interceptors - which I dig.
  • Following up on Interceptors, I was able to easily create my own ValidationInterceptor that cancels validation on GET requests, and when cancel or delete is clicked.
  • Other interceptors that came in handy are a UserRoleAuthorizationInterceptor (which I borrowed from Spring) and an ExceptionHandlerInterceptor (which is modeled after Spring's SimpleMappingExceptionResolver). The 1st interceptor made it easy to mimic Struts' ability to declare a "roles" attribute on an action-mapping. The 2nd one allows you to map exceptions to results. This is something I was looking for when I first started using WebWork.
  • The "required" attribute in WebWork's JSP tags have nothing to do with validation, except that they add an asterisk to the field label. I'd rather this be integrated with validation - where an asterisk shows up when a field is "required" in its Action/POJO-validation.xml file.
  • I had a few other issues with validation: client-side validation shows one error at a time, client-side validation doesn't allow cancelling and field errors are displayed in a random order. If I were to start a project tomorrow that wanted WebWork with client-side validation, I'd probably try to integrate Commons Validator.
  • Testing Actions is easy, as it should be. Using Spring's Servlet API mocks made it easy to test Actions that used ServletActionContext to set cookies and other such request-related stuff.
  • I dig the rich set of form tags and it's great that these can be easily customized. I customized a few for AppFuse to make the syntax a bit more XHTML-compliant.
  • I'm a stickler for formatting and good-looking XHTML in JSPs. I try to keep lines less than 80 characters. Here's a comparison of the LOC required by the different frameworks for userForm.jsp:
    • Struts: 298
    • Spring: 319
    • WebWork: 186

All in all, I enjoyed working with WebWork and if given a choice of an AppFuse combination to use on my next project - it would probably be WebWork+Hibernate. If the client wanted client-side validation, I'd either integrate Commons Validator (which shouldn't be too hard) or use Spring+Hibernate. After using Spring and WebWork, which allow you to use your model objects directly in the view, it would be tough to go back to Struts. However, I still do know Struts better than the other two - so if I had a really tight deadline, that might be the smart way to go.

Posted in Java at Oct 04 2004, 08:17:37 AM MDT 2 Comments

AppFuse 1.6 almost done

I spent many hours and quite a few late nights this week working on AppFuse. It's funny how little sleep you can live on when you're working on something you're passionate about. There's only a few items left on the 1.6 roadmap, so I hope to do a release in the next week or so.

The major new feature in 1.6 is WebWork as a web framework choice. If you'd like to dig in and take AppFuse+WebWork for a test-drive, checkout AppFuse from CVS and execute "ant install-webwork". From there, the tutorials are a good place to start. The QuickStart Guide has more detailed instructions.

If you don't want to do the DAO and Manager stuff, and you'd rather just dig into WebWork, you can download the files from the first two tutorials and extract them into your project.

For a complete list of changes (so far) in 1.6, see the README.txt in CVS. You can also checkout the following demos:

I'll try to write up a detailed post about my WebWork experience in the next couple of days. In the meantime, let's just say I dig it.

Posted in Java at Oct 02 2004, 03:45:49 PM MDT 5 Comments

Playing with JDK 5.0 and Tomcat 5.5.2

I did some experimenting this evening with JDK 5.0 and Tomcat 5.5.2. The good news is that AppFuse compiles fine with JDK 5.0 and runs on Tomcat 5.5.2 nicely too. Here's a couple of things I found:

JDK 5.0
I received a number of interesting errors from the new JDK. Here's one of them:

   [javac] Note: Some input files use unchecked or unsafe operations.
   [javac] Note: Recompile with -Xlint:unchecked for details.

I received a few other messages that were deprecation warnings. The wierd thing is that it was telling me what's deprecated in HttpServletResponse, rather than what's deprecated in my code. Huh - what's the point?

Unfortunately, I found that Cactus won't run on JDK 5.0. Too bad, everything else seems to work fine.

Tomcat 5.5.2
I like the speediness of the new Tomcat, but I was disappointed to find out that they changed the DTD for the context.xml file. The old one works fine on Tomcat 4.1.x and 5.0.x, but you have to make some modifications for it to work on 5.5.x. To be fair, the new syntax is shorter and more concise. I've updated AppFuse's build.xml to detect Tomcat 5.5 and swap context files as appropriate.

Because of the Cactus bug, I think I'll be sticking with JDK 1.4.2 and Tomcat 5.0.28 for now - but it's cool to know that everything else will work once Cactus is fixed.

Posted in Java at Sep 30 2004, 11:32:03 PM MDT 6 Comments

F3 Kills XP

Here's a good one for you. I've been trying to hack my register on Windows XP to enable InnoDB tables in MySQL (which doesn't seem to be working). When I hit F3 to search for the next instance of "mysqld-nt.exe" - it kills my machine. The screen just goes dark and seemingly shuts down (though the power light is still on). If I press the power button, it'll power off fully. Of course, pressing it again powers it back on again. Wierd - guess it's time to switch to OS X for the day.

Thinking out loud: Maybe I should switch AppFuse to using PostgreSQL by default so users don't have to jump through hoops to get transactional tables.

Posted in Java at Sep 22 2004, 12:51:15 PM MDT 20 Comments

[ANN] Cargo 0.1 Released

Vincent Massol has released Cargo 0.1 - an open source project to start/stop and configure Java containers. I'm using its Ant tasks in Spring Live's sample app in conjuction with jWebUnit and Canoo's WebTest and it works great. Here's some sample code:

    <target name="test-web" depends="war"
        description="Runs tests that required a running server">
        <taskdef resource="cargo.tasks" classpathref="classpath"/>
        <cargo-tomcat5x homeDir="${tomcat.home}"
            output="${test.dir}/cargo.log"
            workingDir="${test.dir}/tomcat5x" action="start">
            <war warFile="${dist.dir}/${webapp.name}.war"/>
        </cargo-tomcat5x>
        <property name="testcase" value="WebTest"/>
        <antcall target="test"/>
    </target>

Read more about Cargo's beginnings on TheServerSide.com. This initial version provides:

  • A Java API to:
    • Start containers
    • Stop containers
    • Configure containers for deployment in any user-specified directory
    • Wait for containers to be started
    • Wait for containers to be stopped
    • Supports WAR and EAR static deployments
  • Ant tasks that wraps the Java API

Good stuff - thanks Vincent!

Posted in Java at Sep 11 2004, 08:47:17 PM MDT Add a Comment

No G5 PowerBooks Anytime Soon

Mac Rumors: No G5 PowerBooks Anytime Soon. If I had a vote, I'd say it's time to give up on the G5 for the PowerBook and make OS X run on Intel or AMD chips - then produce an Intel/AMD version of the PowerBook. Apple makes great hardware, but their laptops are much slower than their Intel counterparts (for Java at least). All I want is a PowerBook that can keep up with an Intel-based laptop - is that too much to ask?

Posted in Mac OS X at Sep 01 2004, 04:18:34 PM MDT 16 Comments