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 "jvm". 113 entries found.

You can also try this same search on Google.

How do I attach a profiler to Ant?

I'll admit, I have very little experience working with a profiler - but I think I need one. Someone e-mailed me about testing all of AppFuse on a super-beafy box, and he got OOM errors after 17 minutes. For a dual CPU, 2Ghz Opterons, with 2GB RAM running RHEL3 workstation, it only made it to the Spring/AppGen test, which is #8 of 21. On my PowerBook, it makes it to #12, but my Linux box only make it to #8 too. My guess is there's some sort of memory leak in one of the testing tools - Tomcat, Cargo, WebTest or AppFuse itself.

Anyone have experience attaching a profiler to their Ant build or testing process to look for memory leaks?

Posted in Java at Dec 12 2004, 10:55:35 AM MST 10 Comments

Can you test all of AppFuse?

I'll admit, it's time for me to get a G5. I can no longer test everything in AppFuse in one fell swoop. When I try to run this Ant build file(info) (which I'd like to use with CruiseControl) on my Mac and Linux machines, I get OutOfMemory errors. My PowerBook has ANT_OPTS set to "-Xmx768m" and my Fedora Core 3 box has it set to "-Xms1024M -Xmx1024M". Both machines have 1 GB of RAM. The build dies a lot sooner on Linux (15 minutes), and the PowerBook gets really close to finishing (42 minutes). I'm guessing all the tests would take about 50 minutes on the PowerBook. There are currently 21 AppFuse combinations tested by this script. Spring is used in all of these, so I've eliminated that as a listed option.

NOTE: If you're trying this on Windows, remove the "fixcrlf" call at the beginning of the "test" target.

  1. Struts + Hibernate
  2. Struts + Hibernate and iBATIS
  3. Struts + iBATIS
  4. Struts with AppGen - Generic
  5. Struts with AppGen - Detailed
  6. Spring MVC + Hibernate
  7. Spring MVC + iBATIS
  8. Spring MVC with AppGen - Generic
  9. Spring MVC with AppGen - Detailed
  10. WebWork + Hibernate
  11. WebWork + iBATIS
  12. WebWork with AppGen - Generic
  13. WebWork with AppGen - Detailed
  14. JSF + Hibernate
  15. JSF + iBATIS
  16. JSF with AppGen - Generic
  17. JSF with AppGen - Detailed
  18. Tapestry + Hibernate
  19. Tapestry + iBATIS
  20. Tapestry with AppGen - Generic
  21. Tapestry with AppGen - Detailed

So, the question is - can your machine run all the tests for AppFuse? If so, let me know your specs. I'd love to get this setup for CruiseControl, but if I can't even run it with Ant, I doubt CruiseControl will be any better. I realize I could split things up, but I prefer to have one build file.

Posted in Java at Dec 10 2004, 08:51:02 AM MST 8 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

Using JAAS with Tomcat

Want to use JAAS with Tomcat? If so, you might want to checkout this Using Tomcat with JAAS tutorial.

Although it is possible to use JAAS within Tomcat as an authentication mechanism (JAASRealm), the flexibility of the JAAS framework is lost once the user is authenticated. This is because the principals are used to denote the concepts of "user" and "role", and are no longer available in the security context in which the webapp is executed. The result of the authentication is available only through request.getRemoteUser() and request.isUserInRole().

This reduces the JAAS framework for authorization purposes to a simple user/role system that loses its connection with the Java Security Policy. This tutorial's purpose is to put a full-blown JAAS authorisation implementation in place, using a few tricks to deal with some of Tomcat's idiosyncrasies.

Personally, request.isUserInRole() usually does everything I need. If I need something more than that, it's usually pretty easy to add some custom logic. Of course, if I ever need anything super robust, I'll probably use the Acegi Security System for Spring.

Posted in Java at Jun 03 2004, 10:30:27 AM MDT 3 Comments

[NFJS Denver] Mike Clark and Continuous Performance Testing

I'm sitting in Mike Clark's Continuous Performance Testing talk right now and he's telling us about his experience with performance optimization. Unfortunately, there's wireless access in this hotel's lobby, but not in the (small) rooms. This post is being sponsored by Bluetooth and my T68i. There's two traditional methods of performance tuning - pre-optimization and after-the-fact. He's pointing out that it's most important to have well-factored code - then when you do decide to do performance optimization, it's simply easier to do.

I had lunch with Bruce and Rod Cope (my new boss) has joined us in this talk. It's cool to be engrossed in Java with my friends and peers. Choices for this first session included: EJB CMP, JDO and Hibernate (Bruce Tate), JSF (David Geary), Naked Object (Dave Thomas), Continuous Performance Testing (Mike Clark) and Practical J2EE Security (Tom Marrs).

Back to the talk - Mike is talking about JUnitPerf and how it works. JUnitPerf looks pretty easy to use, below is a simple test.

public class TunesTimedTest {
  public static test suite() {
    int maxTimeInMillis = 1000;
    
    Test test = new TunesTest("testTunes");
    Test timedTest = new TimedTest(test, maxTimeInMillis);
    return timedTest;
  }

  public static void main(String args[]) {
    junit.textui.TestRunner.run(suite());
  }
}

Looks pretty simple huh? I'm assuming that the Test and TimedTest classes are part of JUnitPerf. Next up - Profilers. Use a profiler when your performance tests fail. Low tech profiling (we've all done this) - using System.out.println with a variable and some math that prints out how long it took for a method to run. Even better - using a "Profiler" utility class that does that math for you and has start() and end() methods. Medium-Tech Profiling - JVMPI using -Xhrunprof. It spews out a whole bunch of information so you can see how long methods take to run. The problem with it? It spits out ALL the information from the JVM and your class/methods end up at the bottom of the stack. Sounds like too much information for me. Mike's take: hprof is a sledgehammer that is basically unusable in a J2EE environment. In JDK 1.5, JVMPI is going to go away and it will be replaced with JVMTI (Tool Interface). He also mentions JFluid and Dynamic Bytecode Generation

High-Tech Profiling: JProfiler, OptimizeIt, JProbe - all of which use JVMPI. Mike likes JProfile b/c it's cheap and recommends looking at javaperformancetuning.com for open source tools.

Performance Testing Cycle

  • Choose a measurable performance goal
  • Write an automated performance test
  • Run the test to baseline performance
  • Profile the code to identify hot spots
  • Tune one thing
  • Run the test again to measure progress
  • Repeat until performance goals are met

As I blog Mike's presentation, I'm starting to realize there's probably not much point to doing what I'm doing - regurgitating his presentation on the web. A better way to "blog this" event (IMO) would be if I could merely provide my thoughts and comments about each presentation I attend. The presenters will certainly get more out of it, and readers will probably enjoy the post more. But that's the hard part. It's easy to blog as a presenter speaks - but it's hard to formulate your thoughts and opinion as they speak. It's easy to blog your thoughts after the fact, but that's supposed to be the best part of NFJS - the hallway conversations b/w sessions. I could miss the first 10-15 minutes of each new presentation writing about the old one, but that's no fun either. I guess I just need to start thinking faster, formulating my opinions as fast as possible and writing them down. From now on, I'm going to try to refrain from regurgitation and go more for opinionated reporting. Is that what you'd prefer? If my readers want regurgitation, I can continue that route - I just think it makes for boring entries.

Man, these are long sessions. I just looked at the schedule and all the talks today are 1 1/2 hours! That's too long IMO. I'd loathe it as a speaker and as an attendee - I'd prefer 45-60 minute presentations. Mike's a good speaker, but it's tough to keep anyone's attention for more than an hour - unless it's something like soft core porn.

Choices for the next session are: Programming with Hibernate (Tate), Rapid UI Development (Geary), OpenSource Ecosystems (Thomas), Java Classworking (Dennis Sosnoski) and Getting Fit (Daniel Steinberg). I'm leaning towards Rapid UI Development or OpenSource Ecosystems.

Posted in Java at May 21 2004, 02:09:30 PM MDT Add a Comment

Setting the heap size on your JVM

Cameron has posted a comment on my Performance Tuning MySQL article. The reason I'm highlighting this because it's something I wasn't are of:

From the article:

    -Xms128m -Xmx256m

The Sun JVM will run significantly faster with the following config instead:

    -Xms256m -Xmx256m

That's because the Sun implementation acquires and releases memory from / to the OS way too aggresively if the "ms != mx". Furthermore, either your server has the 256MB available or it doesn't. If you don't have it available, don't set the max that high. If you do have it available, you gain nothing from setting the min lower. This isn't a desktop system, it's a server -- make sure you have the necessary resources and if you do then use them!

Time to change all my heap size setting since I've been using the first setting (128/256) for quite some time. Thanks Cameron! The real question is: will changing "-Xms256m -Xmx512m" to "-Xms512m -Xmx512m" speed up my slow-ass PowerBook? ;-)

Posted in Java at Apr 28 2004, 09:16:00 AM MDT 7 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

i18n - synching up Struts and JSTL

As he did with Roller, Jaap van der Molen made some enhancements to AppFuse to fully support internationalization. He also translated all the existing keys to Dutch. What a guy, eh?!

After I installed this enhanced version of AppFuse, I noticed a few quirks. Namely that my default language was Dutch. To me, this meant that my browser's local must be Dutch. However, since it wasn't, I knew there had to be an issue. After a bit of Googling, I found my answer. It turns out that if you don't specify the language on your default properties file, JSTL won't pick it up - and it defaults to the first one with a language specified. This means that you must have ApplicationResources_en.properties instead of ApplicationResources.properties. Also, another quirk is that you need to synch up Struts locale-setting and JSTL's locale-setting. To do this, I added the following method to my ActionFilter.java class:

    // keep JSTL and Struts Locale's in synch
    Locale locale = (Locale) session.getAttribute(Globals.LOCALE_KEY);
    if (locale == null) {
        locale = request.getLocale();
    }
    if (request.getParameter("locale") != null) {
        locale = new Locale(request.getParameter("locale"));
    }
    session.setAttribute(Globals.LOCALE_KEY, locale);
    Config.set(session, Config.FMT_LOCALE, locale);

Even with all these "hacks" - Mozilla and Safari handle this stuff differently on the Mac. Jaap says that everything works fine on Windows w/o these hacks, so maybe it's just an OS X thing. Regardless, to make things easier, I've added the ability for users to switch between languages by clicking on their language of choice.

There's nothing like adding a new feature to something you're about to demo! I'm on in 45 minutes - the butterflies are fluttering like mad...

Posted in Java at Apr 15 2004, 12:42:00 PM MDT 9 Comments

Groove Systems: Cheap Java Hosting Provider

Spotted on the WebWork Mailing List today. Groove Systems (Rick Salsa's employer) has some nice hosting solutions. I currently pay $30 (Canadian) for 200 MB, 5 GB Transfer and my own JVM at KGBInternet.com. Keith (at KGB) rocks because he is always quick to respond to any of my issues and always tries to help me out. However, I have to admit, Groove's Grooviest package looks pretty nice. For the same price ($30 Canadian), you get 1 GB space, 15 GB Transfer and your own JVM.

The only question I have is how much memory do you get? Keith does nothing to limit memory usage, so I'm currently set at a 512 MB max heap size. Who knows if I'm using it all, that's just what I'm set at. Oh and one other thing you might like to know:

... right now you can get a 32meg private jvm for free.

Read the read e-mail from Rick for more info.

Posted in Java at Mar 10 2004, 12:54:11 PM MST 3 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