Matt RaibleMatt Raible is a Web Developer and Java Champion. 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 "java". 1,588 entries found.

You can also try this same search on Google.

DB2 JDBC Driver

Since most folks come to this site from Googling errors, here's a new one for you - complete with a solution! When I tried to connect from OS X to a DB2 database today, I received the following error:

java.sql.SQLException: java.lang.UnsatisfiedLinkError: no db2jdbc in java.library.path
        at COM.ibm.db2.jdbc.app.DB2Driver.<init>(Unknown Source)

The reason this happens is because there are two JDBC Drivers for DB2 - the first is a native type-2 driver (signified by app in the classname) and the 2nd is a type-4 driver (signified by net in the classname). This page describes the difference between the DB2 JDBC Drivers.

To solve this issue, I changed my JDBC classname to be COM.ibm.db2.jdbc.net.DB2Driver and the error went away. Of course, the type-2 driver is faster, but since there is no client for DB2 that I can install on OS X, I'll still with .net. on the Mac, and .app. with the DB2 client on Windows. Of course, I prefer no client install - it just seems cleaner and easier to me.

The Next Day: I also discovered that it's very important that your db2java.jar file is really the db2java.zip file from the server. If the versions don't match (i.e. trying to connect to a 7.2 db with an 8.1 driver), it actually kills the JDBC Listener! What a pile of...

Posted in Java at Jan 12 2004, 05:57:34 PM MST 1 Comment

The Verge Web Framework

After reading this post on the Server Side, I'd hate to be the guy who invented Verge. He's getting pounded like a rabbit during mating season!

Personally, I don't think there's anything wrong with another web framework. Competition is good. The funny thing is that I've never had a need to migrate away from Struts. I do admit that the IoC (Inversion of Control) in WebWork looks cool, but I don't have a need. After reading most of Rod Johnson's J2EE Design and Development, I do understand IoC (I didn't have a clue before), but I still don't see how I need it. I've never run into a problem with Struts that I couldn't solve. Maybe it helps that I've written my own app to make Struts development simpler.

Even though I do like Struts, and I do find it easy to develop with, I also plan on stuffing my head in a couple of books and learning all about Spring, Tapestry and WebWork. Why? Mainly because I'm a fool and I can't be happy just sitting on the couch and watching TV (which would probably help my blood pressure and make my family happier). I'm a fool because I'd rather learn than relax. Back to the point - why do I want to learn these "big 3?" To be honest, it's primarily because some big names (and folks I'd consider friends) are saying they're cool and they'll make my job easier. If only I wasn't so easily influenced...

What I hate about all of this is that as soon as I decide to integrate Spring into AppFuse, it becomes more complicated. Yes, an XML BeanFactory file is more complicated than Interface i = new InterfaceImpl(), especially for newbies.

Furthermore, I'm willing to bet that I'll end up writing workarounds for issues I encounter in Tapestry and WebWork. I'll even put my money where my mouth is - if your framework doesn't require me to write any workarounds, I'll donate $100 to the project. Heck, if it really is that cool - I'll donate money regardless of workarounds.

The worst part is that there's really no reason to convert my Struts webapp to these newer, cooler frameworks. About the only good reason is so I can say "I know the XXX Framework." I doubt XXX Framework will make anything easier, but it certainly might make my webapp a whole lot cooler. wink

Posted in Java at Jan 12 2004, 03:57:49 PM MST 13 Comments

AppFuse on DB2 and WebSphere

I did some trial-and-error this morning, and with the help of a lot of handy-dandy unit tests, I got [Appuse working on DB2|AppFuseOnDB2]. I learned that I need to figure out how to create a database with page size = 8 by default - anyone got a SQL script to create DB2 databases (with reasonably sized table spaces) lying around?

Next up: Getting AppFuse running on WebSphere 5.1, this should be fun. Especially considering that they only seem to support .ear files, not .war files. I've only glanced at the thing for 5 minutes - any advice/links would be awesome.

Posted in Java at Jan 12 2004, 10:23:11 AM MST 9 Comments

SourceBeat - would you buy a subscription?

I came across this site last week and I'm wondering what Java developers think of it?

SourceBeat Logo

How it works differently than the traditional publishing model is that instead of buying one static book, users will subscribe to a particular book for 12 months. The expert authors provide updates each month on their respective topics, ensuring that you always have the latest and greatest information on your topic. No more buying multiple books on the same topic in order to cover all the areas you need. In addition, as a subscriber you can interact with the author through list servers and weblogs. This way you can let them know your thoughts on current items and also what you would like to see in future updates.

It sure sounds like a good model, but would you buy a subscription? Personally, I hate online books (HTML or PDF) because I like to have a book in front of me. I like to take books to the library or to a quiet room, eliminate distractions, and read. If I'm on the computer reading, I get distracted and end up reading blogs or writing code. The model seems cool though - the ability to shape an authors writing and get them to cover topics on whatever technology you're subscribed to. It'd be cool if it was only $29.95/year for all books rather than each book, but it's probably still cheaper than buying books from your favorite bookstore.

Posted in Java at Jan 10 2004, 05:51:16 PM MST 1 Comment

What should I learn next?

I received an e-mail a few minutes ago from an old friend. We used to work together at eDeploy, which has finally gone out of business, 2.5 years after they closed their doors. This was my last full time job and was also my favorite job of all time. I rode my bike to work, got to learn Java, wore shorts all the time, and thoroughly enjoyed our Friday lunches.

His questions were fairly simple:

  • What is the best way to find a Java job/contract in Denver?
  • Since you've had a lot more exposure to what technologies are being used more than others, is there somethings that I should brush up on while I've got the time off (i.e. struts, xslt, EJBs, . . .)?

I wrote a long answer and thought others might be able to benefit from it - so here it is (please add your own advice as you see fit):

What I'd recommend is to subscribe to the following local mailing lists:

RMIUG Jobs: RMIUG Jobs: http://rmiug.org/html/email_lists.html
DJUG Jobs: http://www.denverjug.org/resources/mailinglist.html

They get a fair amount of jobs that come across the wire, and I actually got 2 gigs last year through the RMIUG list. Struts is definitely one of the hottest skills, but I continue to get a lot of calls as a UI/Java Developer. Having the ability to write clean and pretty HTML as well write Java seems to be rare. To complement Struts, I'd focus on JSTL and JSP 2.0. You can't go wrong learning more about Ant and JUnit - I think a lot of people know JUnit, but not many put it on their resume.

You could check out my AppFuse application which uses all of these, as well as Hibernate (another hot one) for the persistence layer.

I started writing AppFuse when I wrote a couple chapters for Pro JSP last year. I use it on all my projects and it really helps accelerate the whole JSP/Struts/JUnit/Tomcat development cycle.

I'd also recommend reading a couple of really great books:

Java Development with Ant: a truly awesome book
Pro JSP: of course ;-)
J2EE Design and Development: I'm reading it right now

EJBs are a thing of the past - you might be able to get a gig doing them, but they're definitely waning. Rod Johnson (author of the 3rd book) wrote the Spring Framework as part of the book, and it's a pretty slick framework for taking the ugly out of J2EE. The project is getting a lot of press, and I hope to use Spring pretty soon to bind all my components together in AppFuse.

Above all else, I recommend starting to read weblogs (a.k.a. blogs), and if you like it, start your own. The best place to start reading them is JavaBlogs, JRoller and Java.net. I'm a committer on the open source project (Roller Weblogger) that runs JRoller. It's some damn slick blogging software. I host my site at KGBInternet for a measly $20/month and I get my own instance of Tomcat to screw up. Reading blogs is definitely the best way to stay on the bleeding edge of Java (and any other industry for that matter).

Posted in Java at Jan 09 2004, 12:38:04 PM MST 1 Comment

The Battle of the GZip Filters

When I first added a Compression/GZip filter to AppFuse, I used the one from Roller, which I believe Lance found in this book. This has worked fairly well since I added it in July last year. When I discovered that there were issues with it on Resin, I chaulked it up as "no big deal" since I don't use Resin anyway. But yesterday, when I discovered that it stopped my apps from displaying my 403 <error-code> page, that was the last straw. I remembered seeing the "Two Servlet Filters Every Web Application Should Have" article on ONJava.com about a different implementation, so decided to download the source and try it out.

I quickly discovered that this Filter does work on Resin, so that's quite a bonus. I've had issues getting Roller to work on Resin with the Filter enabled, so I might have to replace Roller's CompressionFilter. However, I did still have to change a few things to convince this Filter to satisfy my needs.

Here are a few things I discovered about this GZIPFilter vs. Roller's CompressionFilter:

  • Don't download the GZIPFilter from the article. There is a newer version of the code. Not much has changed, save for an almost completely re-written GZipResponseStream.java file. This one supposedly does better handling of large files.
  • This Filter has the same problem I experienced with Roller's CompressionFilter: JSP pages don't finish rendering when running my Canoo WebTests. I'm assuming that this is because the buffer hasn't finished spitting out HTML. I ended up writing a new isGZIPSupported() method (in GZIPFilter.java) to do the check for GZip support. This allows my webtests to run smoothly by disabling the filter for HttpUnit.
  • This Filter shares another issue that I found in the CompressionFilter yesterday. When my webapp returns an HttpServletResponse.SC_FORBIDDEN error code (from trying to access a method that denies the users role), the Filter suppresses the error and the user is not served up the 403 error page defined in my web.xml. To fix this, I overrode sendError() in GZIPResponseWrapper.java and added a check for this error code in the getWriter() method.

Overall, I'm pleased with this code because I love the concept of GZip Filtering, and now it's not causing any conflicts in my app or targeted appservers.

GZIPFilter.isGZIPSupported(HttpServletRequest):

    private boolean isGZIPSupported(HttpServletRequest req) {
        String browserEncodings = req.getHeader("accept-encoding");
        boolean supported =
            ((browserEncodings != null&&
            (browserEncodings.indexOf("gzip"!= -1));

        String userAgent = req.getHeader("user-agent");

        if (userAgent.startsWith("httpunit")) {
            if (log.isDebugEnabled()) {
                log.debug("httpunit detected, disabling filter...");
            }

            return false;
        else {
            return supported;
        }
    }

GZIPResponseWrapper.sendError(int, java.lang.String):

    public void sendError(int error, String messagethrows IOException {
        super.sendError(error, message);
        this.error = error;

        if (log.isDebugEnabled()) {
            log.debug("sending error: " + error + " [" + message + "]");
        }
    }

GZIPResponseWrapper.getWriter():

    public PrintWriter getWriter() throws IOException {
        // If access denied, don't create new stream or write because
        // it causes the web.xml's 403 page to not render
        if (this.error == HttpServletResponse.SC_FORBIDDEN) {
            return super.getWriter();
        }

        if (writer != null) {
            return (writer);
        }

Posted in Java at Jan 09 2004, 11:30:43 AM MST 15 Comments

Cactus and Form-Based Authentication

Quick Summary: Did you know it's possible to login (with form-based authentication) before running each of your testXX methods in a ServletTestCase or CactusStrutsTestCase? Just add a "begin" method in your Base class, or in each of your Tests, and it will be called automatically, just like setUp() is called.

    public void begin(WebRequest request) {
        request.setRedirectorName("ServletRedirectorSecure");
        request.setAuthentication(new FormAuthentication("tomcat","tomcat"));
    }

Long and Winded: Yesterday, I began adding the "roles" attribute to my Struts action-mappings - to limit access for certain user roles (Yes, XDoclet 1.2 supports this). This worked great in my web UI, until I tried to run my StrutsTestCases. Access was denied because I was not logged in. Rather, I was "faking it" by retrieving a UserForm object in my setUp() method and stuffing it into the session [View Source]. This worked like a charm until I added the roles restriction.

Cactus has a nice feature: if you write a beginXX method, it will be called before your testXX method. In other words, begin = client, test = server. So I added a number of beginEdit, beginSave, etc. method to my Action Tests. Great - everything worked. But it was ugly to add all those beginXX methods. Then, via Vincent Massol's wisdom, I learned of the global begin(WebRequest wr) method. Now I simply have a begin() method in my BaseStrutsTestCase class, and everything works as smooth as pie.

    public void begin(WebRequest request) {
        request.setRedirectorName("ServletRedirectorSecure");
        request.setAuthentication(new FormAuthentication("tomcat","tomcat"));
    }

A couple of issues I discovered:

  • If you have an Action that doesn't have any roles in any of it's mappings, this will fail, so you have to override the begin() method with an empty {} method in your *Test.class. I believe the error message was it couldn't find the SecureServletRedirector.
  • You must define all the roles (you plan to authenticate with) in your Ant build.xml file. [Read More]
  • My <error-code>403<error-code> is not working on AppFuse or the current real-world app I'm working on. [Read More]

All in all, I'm pretty pumped that Cactus makes it this easy to test my app in its true production environment.

Later: I figured out the source of the 403 error-page not rendering. Once again, my Compression Filter does more harm than good. I switched it out for a more recent GZIPFilter and the same thing happens. The good news is that the new filter works on Resin, whereas the old one did not.

Posted in Java at Jan 08 2004, 01:46:32 PM MST Add a Comment

HowTo: Get an input field's value with Canoo's WebTest

I should start this by saying that I love Canoo's WebTest. It allows you to test clicking through your webapp as if you're using a browser. You simply write your tests in an XML file (which is really an Ant build file), and then run it with Ant. Usually, in my webapps, I write simple tests for CRUD on entities - i.e. EditUser (tests pulling up the edit screen), SavePosition (edit and save, verifies next screen's title), SearchUsers (verifies list screen's title).

One of the issues I had this morning was testing a wizard with WebTest. This was because I didn't know how to get the id of the new record after it was added. Now I found a way. Let's say you have a Create a Job wizard. On the first screen, you enter the job, and on the second, you add the required skills, on the third, you view a summary. To get the new id of the job, you can use XPath to get the hidden field named "jobId" - to do with what you may (i.e. click on a link to the third screen). Here's how: {{{ }}} This is especially helpful because I tend to use a lot of onclick handler's (with location.href's) on buttons (so I don't have to submit to the same action). I also turn off JavaScript for my tests - by not including js.jar in WebTest's classpath. I can't say enough about this tool - the ability to test your app, with JavaScript turned off, and verify that everything works... that's just cool. Especially when you're a JavaScript junkie like me.

Posted in Java at Jan 06 2004, 05:25:15 PM MST 5 Comments

[IDEA 4.0] Favorite Feature = Package View

IDEA 4 Package View My favorite feature of IDEA 4.0 is the package view. Since I keep my src and test trees separate, but their package structures identical, this is the view I've been longing for. Hopefully it's possible with Eclipse and I just haven't figured it out. What it does is allow me to see tests right next to my classes. In Eclipse, I have to constantly navigate between the two trees to edit tests and such.

Does this mean I like IDEA better than Eclipse? No, it simply means that I wish Eclipse had this feature, and I appreciate IDEA for adding it.

Posted in Java at Jan 05 2004, 12:18:42 PM MST 4 Comments

Running AppFuse on Resin

Want to run AppFuse on Resin? I did some research (a.k.a. banging my head against the wall) and figured out how this morning. It isn't too tough, now that I've figured out how. You can read about my journey on my wiki, or follow the following steps (for the CVS version):

  • Edit $RESIN_HOME/conf/resin.conf and add the following after the last </web-app> closing tag.
<resin:include href='appfuse.conf'/>
  • Download appfuse.conf(info) and put it in the $RESIN_HOME/conf directory.
  • Put activation.jar, mail.jar and mysql-connector-java-3.0.9-stable-bin.jar in $RESIN_HOME/lib.
  • Remove password encryption by changing the Login Servlet's encrypt-password init-param (in web.xml) to false. You can do this in the build process by changing "encrypt.password" to false in app-settings.xml. You could also do it from the command line using -Dencrypt.password=false. For testing, you will need to change a number of files that have the encrypted password. Search for "536c0b339345616c1b33caf454454d8b8a190d6c" and change it to "tomcat".
  • Remove the <filter-mapping> for CompressionFilter.
  • To enable the "Remember Me" feature, remove the <c:if test="${rememberMeEnabled}"> check in loginForm.jsp. (AppFuse 1.3-dev)

DISCLAIMER: I did not thoroughly test that everything works, I just ran through a couple of pages.

Posted in Java at Jan 04 2004, 09:47:43 AM MST