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 "matt". 663 entries found.

You can also try this same search on Google.

RE: Wrox Going Under

Matt hopes for for Professional JSP 2.0:

[Larkware] A couple of weblogs have reported that Wrox is going under. Although at the moment this has to be classed as "credible rumor," it really doesn't surprise me, on two fronts. First, it seems to me that Wrox's strategy for the past year or so has been mainly "throw a lot of stuff at the wall and see what sticks."

I really really hope not. I was looking forward to Professional JSP 2.0...

Yeah, I was really looking forward to this book - my first time being published, busting my hump to write just after having a new daughter, among other things. It just sucks. It doesn't really suck for me, it really sucks for the people that actually worked for Wrox. As for Professional JSP 2.0, who the heck knows what'll happen. I really hope it gets published. I also hope to get paid for writing, but that'll probably never happen. If they don't publish it, they probably don't have to pay the authors. I think the book is done though, maybe we can talk them into publishing it... Let's get a petition going!

Or maybe I'll just sell my chapters on eBay.

Posted in Java at Mar 15 2003, 10:00:20 AM MST 3 Comments

Hibernate Enhancements

For you Hibernate users/lovers, here's some good news for you (THANKS GAVIN!):

1. [Hibernate Forum] For XDoclet users its well-worth grabbing a CVS update now, I have fixed a bunch of issues and made improvements including Hibernate2 support (thanks to Matt Raible) and joined-subclass support.

2. [Hibernate Dev List]

 After a bit of research and thinking, I have settled on an approach to
 query by Criteria that hopefully is flexible enough for 80-90% of use
 cases, but still simple enough to fit in sufficiently few lines of code.
 
 The proposed new API is based loosely upon the Cayenne API. Queries may be
 expressed as follows:
 
 
 List cats = session.createCriteria(Cat.class)
     .add( Expression.like("name", "Izi%" ) )
     .add( Expression.between("weight", minWeight, maxWeight) )
     .add( Expression.eq( "mate", mate ) )
     .addOrder( Order.asc("age") )
     .setMaxResults(20)
     .list();
 
 
 Which is approximately equivalent to:
 
 from Cat cat
 where cat.name like 'Izi%'
 and cat.weight between :minWeight and :maxWeight
 and cat.mate = :mate
 order by cat.age
 
 
 This API is marked "experimental", but I would like to stabilize it fairly
 soon, so early feedback is very welcome. This is all in CVS.

Posted in Java at Mar 09 2003, 09:56:16 AM MST 3 Comments

How do I remove duplicates in a List?

I have a List that may contain duplicates and I need to filter out the duplicates (so I don't get a foreign key violation when inserting records). Are there any Jakarta' Commons utilities to do this? I can see a few solutions to my problem:

  • Present it on the UI. This might be tough since I'm using a select box JavaScript library. Hmmm, I am using a custom setter for the String[] that gets sent in, maybe I can do it there - checking to see if the ArrayList I'm setting already contains the given String.
  • Filter it out in the business layer.
  • Use a type of List that doesn't allow duplicates, and just ignores a duplicate value when you try to add it.

I just thought of #1 while writing this post. It's cool how talking about your problems can help solve them - no wonder shrinks get paid so much. I'm still interested in any proposed utility classes.

Posted in Java at Mar 08 2003, 07:15:42 AM MST 5 Comments

Debugging JUnit tests in Eclipse - how?

Does anyone know how to run JUnit tests using Ant and debug them in Eclipse? I have the JUnit/Ant part figured out, it's the debugging I'm having issues with. I'm able to run debug (using breakpoints) in Eclipse while running Tomcat, but not while running a simple JUnit test from Ant. Man that would be cool. If I could run Ant (from w/in Eclipse or on the command line) and set breakpoints in Eclipse - I could sure speed up my development time.

Posted in Java at Mar 07 2003, 09:15:09 AM MST 3 Comments

No Fluff, Just Stuff - I'm In!

If I play my cards right, I'll be either (1) flying back from Florida for this conference, or (2) moving to Florida shortly afterwards.

------------------------------------------------------
Confirmation number: 338104
Name: Matt Raible

------------------------------------------------------
Rocky Mountain Software Symposium 2003: Spring Edition

Date: Friday, May 16, 2003 - Sunday, May 18, 2003

Sheraton Denver West
360 Union Blvd
Lakewood, CO  80228


Posted in Java at Feb 28 2003, 09:16:25 AM MST Add a Comment

Struts Validator: Validating Two Fields Match

In the Struts Validator Guide, there is a section on how to create a pluggable validator that matches two fields. I've been using this server-side validator (as shown in the example) to do password/confirm password validation. This has worked great for me, but I've always wanted the Validator to have the client-side JavaScript method for it too. I wrote my own that just compared the two fields, but it's not the same as having one rendered for you (from validator-rules.xml). So yesterday, I did some tinkering and figured out how to add the JavaScript method to validator-rules.xml. So here's how to configure the whole thing (most of this is contained in the Validator Guide, save the JavaScript).

How To Add a TwoFields Validator

Step 1: Create a class with a validateTwoFields method. In my code, my class is ValidationUtil and has the following method:

public static boolean validateTwoFields(Object bean, ValidatorAction va,
                                        Field field, ActionErrors errors,
                                        HttpServletRequest request) {
    String value =
        ValidatorUtil.getValueAsString(bean, field.getProperty());
    String sProperty2 = field.getVarValue("secondProperty");
    String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);

    if (!GenericValidator.isBlankOrNull(value)) {
        try {
            if (!value.equals(value2)) {
                errors.add(field.getKey(),
                           Resources.getActionError(request, va, field));

                return false;
            }
        } catch (Exception e) {
            errors.add(field.getKey(),
                       Resources.getActionError(request, va, field));

            return false;
        }
    }

    return true;
}

Step 2: Edit validator-rules.xml to contain the "twofields" rule.

<validator name="twofields" 
    classname="org.appfuse.webapp.util.ValidationUtil" method="validateTwoFields" 
    methodParams="java.lang.Object,
                  org.apache.commons.validator.ValidatorAction,
                  org.apache.commons.validator.Field,
                  org.apache.struts.action.ActionErrors,
                  javax.servlet.http.HttpServletRequest" 
   depends="required" msg="errors.twofields">
    <javascript><![CDATA[
        function validateTwoFields(form) {
            var bValid = true;
            var focusField = null;
            var i = 0;
            var fields = new Array();
            oTwoFields = new twofields();
            for (x in oTwoFields) {
                var field = form[oTwoFields[x][0]];
                var secondField = form[oTwoFields[x][2]("secondProperty")];
            
                if (field.type == 'text' ||
                    field.type == 'textarea' ||
                    field.type == 'select-one' ||
                    field.type == 'radio' ||
                    field.type == 'password') {
            
                    var value;
                    var secondValue;
                    // get field's value
                    if (field.type == "select-one") {
                        var si = field.selectedIndex;
                        value = field.options[si].value;
                        secondValue = secondField.options[si].value;
                    } else {
                        value = field.value;
                        secondValue = secondField.value;
                    }
                
                    if (value != secondValue) {
                    
                        if (i == 0) {
                            focusField = field;
                        }
                        fields[i++] = oTwoFields[x][1];
                        bValid = false;
                    }
                }
            }
            
            if (fields.length > 0) {
                focusField.focus();
                alert(fields.join('\n'));
            }
            
            return bValid;
        }]]></javascript>
</validator>

Step 3: Configure validation for your form in validation.xml:

<field property="password"
     depends="required,twofields">
  <msg
    name="required"
    key="errors.required"/>
  <msg
    name="twofields"
    key="errors.twofields"/>

  <arg0 key="userForm.password"/>
  <arg1
    key="userForm.confirmPassword"
  />
  <var>
    <var-name>secondProperty</var-name>
    <var-value>confirmPassword</var-value>
  </var>
</field>

Where errors.twofields=The '{0}' field has to have the same value as the '{1}' field. An alternative to Step 3 is to use XDoclet to generate your validation.xml. This requires (1) configuring XDoclet (of course) and (2) adding some @struts tags to your form on the setPassword method.

/**
 * Returns the password.
 * @return String
 *
 * @struts.validator type="required" msgkey="errors.required"
 * @struts.validator type="twofields" msgkey="errors.twofields"
 * @struts.validator-args arg1resource="userForm.password"
 * @struts.validator-args arg1resource="userForm.confirmPassword"
 * @struts.validator-var name="secondProperty" value="confirmPassword"
 */
public String setPassword() {
	return password;
}

I've sent this as a proposal to the struts-dev mailing list yesterday, but haven't heard anything yet. Enjoy!

Update: You'll need to update ValidationUtil.java and validator-rules-custom.xml for Struts 1.2. Full files: ValidationUtil.java and validation-rules-custom.xml.

Posted in Java at Feb 26 2003, 12:29:56 PM MST 10 Comments

Hibernate Upgade: 1.2.3 to 2.0 (My Story)

I'm upgrading struts-resume to Hibernate 2.0 tonight. I thought I'd blog my adventure and what I needed to change.

Step 1: Patch XDoclet to allow specifying the DTD in the generated .hbm.xml files.

Step 2: Download Hibernate 2.0 beta 2. It's at the bottom of the preceding link.

Step 3: Extract to struts-resume/lib and change lib.properties to version 2.0.

Step 4: Edit build.xml file to pick up the new DTD. I changed <hibernate/> to be <hibernate validatexml="true" version="2.0"/>.

Step 5: Using HomeSite, I did s/cirrus.hibernate/net.sf.hibernate/g. 14 matches. The project currently has 3 DAO's and a ServiceLocator to get Hibernate Sessions.

Step 6: ant clean deploy Not too bad, only one compile error.
D:\source\appfuse\src\ejb\org\appfuse\persistence\ServiceLocator.java:12: cannot resolve symbol
symbol : class Datastore
location: package hibernate
import net.sf.hibernate.Datastore;


Step 7: Open up Eclipse, refresh the project and right click on the project name, click Properties >> Java Build Path. Change path for hibernate.jar to struts-resume/lib/hibernate-2.0/hibernate.jar. Remove the previous path.

Step 8: Go searching for what the heck happened to Datastore. Hibernate CVS is first choice. Pause to post (per chance someone reads and sends solution).

Step 9: Step 4 from the Hibernate 2 Porting Guidelines. Replacing attribute names, DTDs and changed throws SQLException to JDBCException in ServiceLocator class.

Step 10: Repeat Step 5 for all Unit tests (they live in "test," rather than "src"). End up repeating for entire project, makes about 1800 replacements - hibernate-1.2.3/src was in search path. Remove lib/hibernate-1.2.3.

Step 11: Revisit Step 8 and try to use new Configuration API. Tried this...
Datastore datastore = Hibernate.createDatastore() - changed to Configuration config = new Configuration();

Not working yet... But Gavin has responded to the mailing list and Chiara is listening. Good to have the support ;-)

Step 12: Found a problem with XDoclet, modifying source. Changing "role" attribute to "name" for the following types (in order replaced by HomeSite): subcollection, collection, set, bag, list, map, array, primitive-array. Rebuilt hibernate module. Changed attribute "readonly" to "inverse" and tried again. Changes to set and bag only.

Step 13: I'm using the Configure.configure() method to initialize from hibernate.cfg.xml (I had to rename the package for my dialect from cirrus.hibernate.sql.MySQLDialect to net.sf.hibernate.dialect.MySQLDialect). I doubt it'll work though since this expects a JNDI DataSource.

Step 14: Nope, that didn't work. I found out I needed to remove the "length" attribute from any <key> elements in <bag>'s. Back to trying to use config.addClass().

Step 15: Internet connection goes down, reboot router. Change dialect package name in database.properties. This file is renamed to hibernate.properties and used for running JUnit tests. Now time to have fun with JUnit and get UserDAOTest to run.

I'm getting a connection to the database now thanks to Gavin's advice:
sf = new Configuration()
     .addClass(Foo.class)
     .addClass(Bar.class)
     .buildSessionFactory();


Step 16: Changed xdoclet tags "inverse" attribute to be "false" where previously readonly="true", now inverse="false". Now I'm getting the following error:

[junit] java.sql.BatchUpdateException: Invalid argument value: Duplicate entry '0' for key 1
[junit] at com.mysql.jdbc.jdbc2.PreparedStatement.executeBatch(Unknown Source)


Whenever I try to run the addResume test for a user. The mapping looks fine, I'll try dropping and re-creating the database. Found I needed to change the package names in build.xml. Note to upgraders: don't filter by file extension when replacing the package name.

Discovered that the SchemaExport class had moved from net.sf.hibernate.tools to net.sf.hibernate.tool.hbm2ddl.

Step 17: The UserDAOTest runs successfully. Now for the web...

Couldn't get "ant test-canoo" (Canoo WebTest) to run until I copied xerces.jar back into lib/hibernate-2.0/lib. Changed my log4j.properties to use new package name for logging.

After looking at some 2.0 documentation, I discovered a new DTD for hibernate-configuration. Unfortunately, it's not there. So I put it on this site as a workaround. Got rid of startup errors. One change in the DTDs is that all <property> declarations must be within a <session-factory> element.

Now I can't get Hibernate to connect to JNDI. Back to the doco...

(5 minutes later) Yep, right in the doco. I changed StartupServlet.java to have the following:
SessionFactory sf =
  new Configuration().configure().buildSessionFactory();


Now, when I login I'm getting:

java.lang.UnsupportedOperationException
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:125)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:329)


Since my Unit tests on the business level run, I'm guessing it's something wrong with this line in hibernate.cfg.xml:
  <property name="connection.datasource">java:comp/env/jdbc/resume</property>

Get a good nights sleep; zonked out at 3, up at 8:30 to continue...

Step 18: Find out (from Gavin) that there's probably a hibernate.properties file in my classpath that is causing the problem. I find this fine inside hibernate.jar. Doh! There's an error in packaging. ;-) I remembering seeing this sometime last week on the mailing list. I decide to upgrade to Hibernate 2.0 beta 3, which was released while I was sleeping. The file hibernate.properties is removed from hibernate2.jar in this release. I did have to update lib/lib.properties to handle the change of jar-name. Compiling, testing...

Dropped and re-created the database b/c I was getting duplicate key errors. Ran UserDAOTest - BUILD SUCCESSFUL - run it again - BUILD FAILED.

Further updates to hibernate-properties.xdt to replace paramName="role" to paramName="name", also replaced paramName="readonly" with paramName="inverse". Sent an e-mail to xdoclet-devel inquiring about best way to make hibernate-properties.xdt both 2.0 and 1.1-compatible.

This change in XDoclet makes UserDAOTest pass - so it looks like the upgrade is a success. Now I just have to figure out a way to convince the XDoclet team to add support for Hibernate 2.0. This might take awhile, it has for POJO -> StrutsForms support (still pending).

Posted in Java at Feb 23 2003, 11:03:02 PM MST 6 Comments

StrutsCX: Updated

I received the following e-mail from Berny, the author of StrutsCX.

Thanks Matt for hosting a StrutsCX sample. As the author of StrutsCX I do have some news for you: There is a new release with support of FOP/PDF, client side XSLT, XSL pipelineing and included Struts Validator. Check out http://it.cappuccinonet.com/strutscx.

Would be great if you could update on the latest version. Would you mind if I put a link on the StrutsCX Homepage to the Demo?

Thanks,
Berny

I actually upgraded my demo site when I received his e-mail on Saturday, but didn't get around to returning his e-mail until today. I dig the Validator stuff - only seems to be server-side though.

Posted in Java at Feb 17 2003, 08:26:00 PM MST Add a Comment

Easy Windows Authentication with Tomcat 4.x

The original blog entry by Robert Rasmussen has disappeared from the Internet (cannot find server) so I'm reproducing it here via Google's caching feature. I've made a few changes to pretty up the formatting, but that's about it.


I've been pulled into a little internal project, and one of the requirements is that users should be able to authenticate with their Windows login and password. IIS may or may not be in the picture.

Since the server is a Windows 2000 machine, this turns out to be extremely simple to do thanks to Andy Armstrong's JAAS login modules.

Once you've downloaded the login modules, set your classpath accordingly and make sure that the directory holding NTSystem.dll is in your %PATH% variable. Next, in the "Sample config" folder you'll find a tagish.login file and a java.security.sample file. The last line in the .sample file is significant, and it needs to be in your $JAVA_HOME/jre/lib/security folder (in a file named java.security). You should copy the tagish.login file there as well. If your users will always be logging into the same domain (which is the case in my situation), just set the defaultDomain property in tagish.login, like this:

NTLogin
{
    com.tagish.auth.win32.NTSystemLogin required returnNames=true returnSIDs=false defaultDomain=YOUR_DOMAIN_HERE;
};

Now, all you need to do to use Windows authentication in your webapps is to make one addition to your server.xml file (or to your specific context's definition):

<Realm className="org.apache.catalina.realm.JAASRealm" debug="99"
       appName="NTLogin"
       userClassNames="com.tagish.auth.win32.NTPrincipal"
       roleClassNames="com.tagish.auth.win32.NTPrincipal" />

I'll admit this config is slightly hokey. If you look at the Catalina JAASCallbackHandler (which is hardwired to JAASRealm), the way that I have the realm configured above pretty much counts on the User principal (in effect, the user name) being the first principal returned. This is evil, but it works. It would be nice if either Catalina allowed a pluggable CallbackHandler so that I could take advantage of the NTPrincipal.getType() method or if Andy's code returned subclasses of NTPrincipal like UserPrincipal or GroupPrincipal that I could specify in server.xml.

Once you've got this all configured, the various groups your users belong to equate to role names (so if I belong to an administrators group, my authenticated user will be in role "administrators"), and you can configure security in your webapps using these roles.


Posted in Java at Feb 17 2003, 04:11:52 PM MST 19 Comments

Comparative analysis of Struts vs. WebWork vs. Barracuda vs. Maverick?

Does anyone know of a comparative analysis of Struts, WebWork, Barracuda and Maverick. I'd love to find a paragraph or two that I could quote in my chapter on Struts. I'm not at all attempting to say that Struts is better than any of these - I just want to give a fair shake to each one. The reason I'm writing this chapter on Struts is because that's what I'm most familiar with.

Thanks,

Matt

Posted in Java at Feb 17 2003, 09:34:44 AM MST 4 Comments