Wednesday May 24, 2006

More JSF Validation - Custom Error Messages

The errors messages that are shown for each type of validation error are controlled by the Message.properties file, which is located in the javax.faces package of jsf-impl.jar. You can view this file by expanding Libraries > Sun Java System Application Server > jsf-impl.jar > javax.faces and double-clicking Message.properties.

If you want to create custom messages for these errors, you can do so by swapping out the properties file used by the application.

  1. Right-click the jAstrologer project and choose New > File/Folder. Under the Other category, select Properties File and click Next. Name the file MyMessages, put it in the src/astrologer/ui folder, and click Finish. MyProperties.properties opens in the Source Editor.
  2. Copy over the following properties from Message.properties to MyProperties.properties:
    javax.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required.
    javax.faces.converter.DateTimeConverter.DATE_detail={2}: ''{0}'' could not be understood as a date. Example: {1}
  3. Change the values of the properties:
    javax.faces.component.UIInput.REQUIRED=Please enter a value for this field.
    	javax.faces.converter.DateTimeConverter.DATE=Please enter a valid date. 
    javax.faces.converter.DateTimeConverter.DATE_detail=Please enter a valid date. Example: {1}
  4. Open faces-config.xml (under the Configuration Files node) and enter the following inside the main faces-config element:
        ...
        <application>
            <locale-config>
                <default-locale>en</default-locale>
            </locale-config>
            <message-bundle>astrologer.ui.MyMessages</message-bundle>
        </application>
    </faces-config>
  5. Right-click the application and choose Run Project. When you do not enter anything for a required field or enter a bad date format for the birthday field, the application now shows the following errors:

    custom errors

    Note that any messages that you haven't specified in your custom properties file will be taken from the default Message.properties in jsf-impl.jar. Also, you can define a CSS style for error messages and then specify that style in the message tag by doing the following:

    <h:message for="birthday" style="errorMessage" /></p>

Tuesday May 23, 2006

jAstrologer JSF Tutorial - Validaiton Pt. 1

OK, so we've got our basic jAstrologer web application that we've built in the last two exercises. You can download the project here if you haven't run through the last two exercises. Make sure you undeploy any other applications with the /jAstrologer context root that you may have already deployed to the server. So far the web application does the following:

  • Presents greeting.jsp, which uses two inputText components to ask for the user's name and birthday.
  • Saves the values entered by the user in the properties of the UserBean backing bean.
  • Reads the values of the properties from UserBean and displays them in success.jsp.

But was it really a success? In the present state, we don't know. We just take any input (or no input at all) and call it a success. That's why we need to build in a little validation to our web application. We'll start off today with some really basic stuff: making a field required and using a converter to convert the Birthday field from a String to a nice Date object.

Making a Field Required

The first thing we need to do is make sure that the user enters something for the name field. We can easily do this by using the required attribute of the inputText component.

  1. Open greeting.jsp and change the name inputText component as follows:
    	<p>Enter your name: <h:inputText value="#{UserBean.name}" 
    	        id="name" required="true"/>
    	<h:message for="name" /></p>

    What we have done is to give an ID to the name text field, so we can then specify for which component the message shows. We have then specified that the field is required, so the web application will show the error message if the user does not enter anything.

  2. Run the project and click Submit without entering a name. You get the following error:

    no name error

Using a Converter

Now we need to start treating our birthday field as a date and not just a random string. The JSF framework provides a number for converters that you can use to convert text input into object types, like booleans and so forth. In the process of converting the data, it also checks that the data is valid for the type it's converting it into. This is especially handy for our birthday input field because we can specify the date format, validate the input, and get a nice Date object all at once.

  1. Open greeting.jsp and change the birthday inputText component as follows:
            <p>Enter your birthday: <h:inputText value="#{UserBean.birthday}" 
            		id="birthday" required="true">
                <f:convertDateTime pattern="dd/MM/yyyy" />
            </h:inputText> (dd/mm/yyyy)</p>
            <h:message for="birthday" />

    What we have done is to give an id to the birthday text field, so we can then specify for which component the message shows. We have then set the converter to the pattern dd/MM/yyyy. Anything the user enters that does not match this format will cause the web application to redisplay greeting.jsp with an error message. We have also specified that the field is required, like we did with the name field.

  2. Now we need to change the type of the birthday property in UserBean.java to a Date object. Open UserBean.java and make the following changes in bold:
        private String name;
        private Date birthday;
        ...
        
        public Date getBirthday() {
            return birthday;
        }    
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }    
  3. Run the project. When you try to click Submit without entering a date, you get the following error message:

    If you enter an invalid date, you get the following error:

Friday May 19, 2006

jAstrologer JSF Tutorial - Hooking up Backing Beans

Yesterday we created a simple web application with JSF components called jAstrologer. The problem is, our web application doesn't really do anything interesting right now. In order to add rich functionality to your JSF web applications, you can associate your UI components with backing beans, or JSF managed beans whose bean properties and methods are available to the JSF components.

In our example, we'll create a UserBean managed bean that will expose two String bean properties: name and birthday.

  1. Right-click the project and choose New > File/Folder. Under the Web category, select the JSF Managed Bean template and click Next.
  2. Name the bean UserBean and put it in the astrologer.user package. Leave the rest of the settings at their default values and click Finish. The IDE opens UserBean.java in the Source Editor and adds the following bean declaration to faces-config.xml:
        <managed-bean>
            <managed-bean-name>UserBean</managed-bean-name>
            <managed-bean-class>astrologer.user.UserBean</managed-bean-class>
            <managed-bean-scope>request</managed-bean-scope>
        </managed-bean>
  3. Add the following field declarations (shown in bold) to UserBean.java:
    public class UserBean {
        
        String name;
        String birthday;
  4. Now let's generate getters and setters for the fields. Right-click anywhere in the file and choose Refactor > Encapsulate Fields. Click Next in the dialog, then Do Refactoring in the Refactoring window. The IDE switches the access level for the fields to private and creates the getter and setter methods.
  5. In greeting.jsp, make the following changes shown in bold. Note that code completion is available for UserBeans.java and its properties:
        <f:view>
            <h:form>
                <p>Enter your name: <h:inputText value="#{UserBean.name}" /></p>
                <p>Enter your birthday: <h:inputText value="#{UserBean.birthday}" /></p>
                <h:commandButton value="Submit" action="submit" />
            </h:form>
        </f:view>
  6. Add the JSF taglib declarations to success.jsp. You can copy and paste them from greeting.jsp.
  7. Add a JSF form to success.jsp by clicking the JSF Form button in the Palette window and releasing it below the h1 tag in the Source Editor.
  8. Make the following changes to success.jsp:
        <h1>Congratulations</h1>
        <f:view>
            <h:form>
                <p>You've successfully registered with jAstrologer.</p>
                <p>Your name is <h:outputText value="#{UserBean.name}" /></p>
                <p>Your birthday is <h:outputText value="#{UserBean.birthday}" /></p>
            </h:form>
        </f:view>
  9. Right-click the project and choose Run Project. The same greeting.jsp page greets you when the application is deployed.

    greeting.jsp

    When you enter values and click Submit, success.jsp also displays the values you entered, as shown in the following diagram:

    result.jsp

Thursday May 18, 2006

Learn JSF with jAstrologer

I'm working on a new series of tutorials for JSF in NetBeans IDE. We're going to put together an application called jAstrologer, which will take your name and birthday, query a database, call a web service, and spit out:

  • Your zodiac sign
  • Your birthstone
  • The chinese year you were born in
  • A daily horoscope

The first thing is - I hate the name. Anybody out there have a better name? Is there a famous astrologer that we could name this after? A quick search on Wikipedia brings up a certain Guido Bonatti from Forli (which happens to be the arch-nemesis of my town in Italy, Ravenna. Something like Springfield and Shelbyville in the Simpsons.) But I'm not sure about calling it BonattiVision or something.

But I digress... Here's the basic outline of what we want to cover in the series of articles:

  • Getting Started
    • Creating project
    • Creating JSP and declaring taglibs
    • Adding view and form tags
    • Basic navigation
    • Backing bean with simple operation
  • Validating Data and Showing Error Messages
    • Making the birthday field convert to a date, checking for valid entry
    • Checking that the birthday is in the past, not the future
    • Showing error messages for above validation
  • Querying a Database
    • Create an action to take the info, validate, and query db for astrological data
    • Showing data from a data source
  • Localizing and Formatting
    • Extract all display text to properties files
    • Using a CSS to do better formatting
  • Adding Custom Components
    • Incorporating Tomahawk components (inputDate for the date)
    • Setting up the shared libraries on the server
  • Web Service Integration

If anyone has any ideas about things that aren't covered, etc., let me know. So let's just right in and get started. Flash video coming soon.

Getting Started

First we're going to create the simplest web applicaiton possible. We'll just have one JSP page that asks for a name and birthday, then a success page that displays a success page. We'll have the web application display the success page no matter what the user writes in the fields, just to keep things simple.

Creating the Web Application

  1. Create a new Web Application project called jAstronomer. On the third page of the New Web Application wizard, choose to add the Java Server Faces project and leave the rest of the information at its default. Create the project.

Creating the Greeting Page

The IDE creates the web application with a default index.jsp and a welcomeJSF.jsp page. We'll ignore both of these pages and create our own greeting page.

  1. Rright-click the project node and choose New > JSP, name the file greeting, and click Finish.
  2. Now we need to declare the JSF tag libraries in the JSF file. Change the following code:
    <%--
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
    --%>

    To the following:

    <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
    <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

    Notice that you can use the code completion to help put in not just the tag name and attributes, but also the URIs of the tab libraries.

  3. Change the contents of both the title and h1 tags to Welcome to jAstrologer.
  4. Now let's add a JSF form to the file. In the Palette, click the JSF Form button, drag it to below the h1 tag, and release. In the dialog box, leave Empty Form selected and click OK. The IDE fills in the following code in bold:
        <h1>Welcome to jAstrologer</h1>
        
        <f:view>
            <h:form>
            </h:form>
        </f:view>
    
        </body>
  5. We are going to use inputText components to get the user input and a commandButton component to submit the form. In the Source Editor, change the contents of the h:form element to the following:
        <f:view>
            <h:form>
                <p>Enter your name: <h:inputText value="name" /></p>
                <p>Enter your birthday: <h:inputText value="birthday" /></p>
                <h:commandButton value="Submit" action="submit" />
            </h:form>
        </f:view>

Creating the Success Page

Now we're going to create a page that simply says congratulations.

  1. Create a new JSP file as described below. Name the file success.
  2. Change the contents of the file to the following:
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Congratulations</title>
        </head>
        <body>
    
        <h1>Congratulations</h1>
        
        <p>You've successfully registered with jAstrologer.</p>
        
        </body>
    </html>

    Notice that we're just using straight HTML here, so there's no need to declare the JSF tag libraries yet.

Setting Page Navigation

Page navigation in JSF is controlled by the faces-config.xml file, which is located under the Configuration Files node in the Projects window. For each page you set up a navigation rule which contains one or more navigation cases. Like we said above, we're just going to map the submit action from the commandButton to success.jsp, no matter what the user enters in the fields.

  1. Double-click faces-config.xml to open the file in the Source Editor.
  2. Right-click anywhere in the file and choose Java ServerFaces > Add Navigation Rule. Type /greeting.jsp in the Rule from view field and optionally enter a description of the rule.

    The following code is enterd in faces-config.xml:

        <navigation-rule>
            <description>
                handle user input
            </description>
            <from-view-id>/greeting.jsp</from-view-id>
        </navigation-rule>
  3. Right-click inside faces-config.xml and choose Java ServerFaces > Add Navigation Case. Set the following:
    • From View: /greeting.jsp
    • From Outcome: submit
    • To View: /success.jsp

    add navigation case dialog

    Click OK. The IDE enters the following code in faces-config.xml:

        <navigation-rule>
            <description>
                handle user input
            </description>
            <from-view-id>/greeting.jsp</from-view-id>
            <navigation-case>
                <from-outcome>submit</from-outcome>
                <to-view-id>/success.jsp</to-view-id>
            </navigation-case>
        </navigation-rule>

Configuring and Running the Application

Now let's set the IDE to display greeting.jsp when it runs the application and, finally, test out the application.

  1. Right-click the project and choose Properties.
  2. Click the Run node and type /faces/greeting.jsp in the Relative URL field. Then click OK.
  3. Right-click the project and choose Run. The IDE builds the project, starts the application server, deploys the application, and shows the following page in the external browser:

    greeting.jsp

    When you click the Submit button, you see the following:

    success.jsp

So that's it for the very basic intro. Not rocket science, I know. But we've got the basics down and tomorrow we'll start doing more interesting stuff, like hooking it up to a backing bean and so forth. So stay tuned.

Wednesday May 17, 2006

Using Hibernate as the Persistence Manager on GlassFish

There's been a lot of talk about using Java Persistence API to plug in Hibernate as the persistence manager instead of Oracle's toplink, so let's take a look at how you do this. First, you download the Hibernate Core 3.2.0 cr2 and Hibernate EntityManager 3.2.0 cr1 from the Hibernate website.

Then you copy over the correct JAR files from hibernate to the GlassFish lib directory. I can't figure out exactly which JAR files to copy so I copied hibernate3.jar, hibernate-entitymanager.jar, then all of the JAR files in each of hibernate-3.2/lib and hibernate-entitymanager/lib. I tried to read the READMEs in the lib folders to figure out which ones were really required but I was obviously leaving something out because my App Server wasn't starting correctly. If anyone out there knows which JAR files are strictly required please let me know.

Of couse, restart the server if it's already started.

Now start up the IDE and start the Java DB database. Create a web application project (in this case HibernateApp) and add the JSF framework to it in the second page of the New Project wizard. Right-click the project node and choose New > Entity Classes from Database. Set the jdbc/sample database as the Data Source, select the CUSTOMER table (this is an example table shipped with the IDE) and click Next.

Now it's time to create the persistence unit by clicking the Create Persistence Unit button. There's still some bugs that need to be worked out. In the final version the IDE will scan your GlassFish dir and list Hibernate in the Persistence Provider drop-down. For now, you have to create the persistence unit with TopLink and then manually change it in the persistence unit XML. Let's do that now. Set hibernate as the persistence unit name, leave TopLink as the persistence provider, and switch the table generation strategy to None. You have to do the final one because the syntax for the XML generated by TopLink and Hibernate are different.

When you click Finish, our persistence unit is created (persistence.xml under Configuration Files node) and the entity classes are created (under Source Packages). Double-click persistence.xml and swith to the XML view (click the XML button at the top of the editor). Change the provider element to org.hibernate.ejb.HibernatePersistence, as shown below:

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="hibernate" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/sample</jta-data-source>
<properties/>
</persistence-unit>
</persistence>

Now we can quickly generate JSF pages for the entity classes with Geertjan's favorite feature. Right-click the project node and choose New > JSF Pages from Entity Class. Add both Customer.java and DiscountCode.java to the list of selected classes and click Next. Change the package to hibernatesample.controller and click Finish (we won't specifiy a special folder for JSF pages).

And just Run the project. Hopefully it'll work. It didn't for me the first time, I got a 500 error. I restarted the server again and tried again and everything seemed to work. I guess GlassFish didn't register all of the Hibernate libraries first.

OK, now time to show my ignorance. Why would you want to do this? I mean, is it just a matter of personal preference? Is there a performance difference between TopLink and Hibernate? Any illumination you can shed on this would be helpful.

I Don't Like Captivate Either

Finally got my version of Macromedia Captivate going on the Docs Lab machine. Captivate is another program for making Flash demos, and it's the one that others in our docs group use. I really like some things about it and it would be absolutely the greatest program ever if only it didn't put that annoying pause at the beginning of each slide! It makes each mouse motion so painfully slow. I can't for the life of me figure out how to set the default pause at the beginning of each slide. It's at something random like 1.2 seconds. And I just don't have the time to go and edit each slide manually. So I'm giving up on it as well.

Tuesday May 16, 2006

I Don't Like Camtasia

I just had my first experience with , and guess what? It stinks. I thought I'd use a better tool than Wink, since we've got this snazzy docs lab machine set up that has all the tools installed on it. But something's wacked with the installation of Captivate on the machine, so I figured I'd give Roman's favorite tool a whirl.

Well, it just doesn't work for me. It basically just takes one big screen capture, which means the mouse motions are erratic, and it's hard to edit after. I couldn't figure out how to pause the playback, so in trying to do audio (the only reason I didn't do this in Wink) I was constantly rushing what I was saying to keep up with what was happening on the screen. I couldn't even for the life of me figure out how to enter an intro or outro slide to introduce the thing, so I just ended up tossing it (and half a day's work) out.

So I guess it's back to Wink for me. I hear Wink 2 does audio now, I'm downloading it now. Anybody have any good/bad experiences with it?

Thursday May 11, 2006

Swing Tutorial in Matisse - Custom Table Models

The continuing adventures of the Swing Tutorial in NetBeans and Matisse. In yesterday's blog, I talked about how it's a pain that when you define the data for your JTable's model in some defined arrays of strings and objects, the data doesn't show up in the design view.

In real-world applications, however, you're most likely going to define your custom TableModel to do things like access a database. For example, TableDemo.java sets up MyTableModel as an inner class. So how do you get this set up in the IDE?

Once again, we're using the model property editor for the JTable (select the JTable - not the JScrollPane - in the Inspector window and click the button for the model property in the Properties window). One simple way to do this is to switch to Form Connection mode, select User Code, and just enter new MyTableModel(). If you run the file, you'll see the model is properly used. But in the design view, we still see nothing.

A better way is to copy the MyTableModel class to its own separate class, called MyTableModel, of course. Then build the project (you need a binary version of MyTableModel for what we're about to do). Now select MyTableModel in the Projects window and press Ctrl-C, then paste it anywhere in the design view (or select any node in the Inspector and paste). An instance of MyTableModel gets added to the Other Components node.

Now we can go back to the model property editor for the JTable, select From Bean, and select myTableModel1. And voila, the data appears in the design view.

This and much more is coming up in an excellent tutorial being prepared by Talley Mulligan on hooking up a Matisse GUI form to a DB back-end, so stay tuned for the full story.

Wednesday May 10, 2006

Doing the Swing Tutorial in NetBeans: Tables

Trying to go through the Swing tutorial in NetBeans has always been hard, simply because the code looks so much different than the code that NetBeans uses. You can't just copy and paste their code in, because then you wouldn't be able to see the form in the design view. And of course, the samples don't use Matisse for layout rules, and really why would you use anything else?

I decided to try and power my way through some of the examples anyway. First stop: tables. I'm gonna look at some code, like SimpleTableSelectionDemo.java, and try to reproduce it in NetBeans.

Warning: I know very little about GUI development so this is a case of the blind leading the blind. I will most likely do things that will make real developers grimace. If so, please tell me.

First create a Java Application project with no main class. Create a JFrame called SimpleTableSelectionDemo and just put a JTable into it, expanded to all four sides of the JFrame so it resizes correctly.

Now we encounter the first problem - getting the column values and names into the table and populating it with some data. The example creates two arrays and uses the arrays to set these:

   final String[] columnNames = {"First Name",
                                 "Last Name",
                                 "Sport",
                                 "# of Years",
                                 "Vegetarian"};

   final Object[][] data = {
       {"Mary", "Campione",
        "Snowboarding", new Integer(5), new Boolean(false)},
       {"Alison", "Huml",
        "Rowing", new Integer(3), new Boolean(true)},
       {"Kathy", "Walrath",
        "Knitting", new Integer(2), new Boolean(false)},
       {"Sharon", "Zakhour",
        "Speed reading", new Integer(20), new Boolean(true)},
       {"Philip", "Milne",
        "Pool", new Integer(10), new Boolean(false)}
   };

        final JTable table = new JTable(data, columnNames);

But the IDE just the arrays straign into the parameters of DefaultTableModel:

jTable1.setModel(new javax.swing.table.DefaultTableModel(
   new Object [][] {
   {null, null, null, null},
   {null, null, null, null},
   {null, null, null, null},
   {null, null, null, null}
   },
   new String [] {
   "Title 1", "Title 2", "Title 3", "Title 4"
   }
));

Not a big deal, the model property editor can be used to set this. To open the editor, select the JTable in the Inspector window (not in the Design Area, because that just selects the JScrollPane that the JTable resides in) and in the Properties window click the model property. We can do one of the following:

  • With Select Mode set to TableModelEditor at the top, just enter the column names and types in the Table Settings tab and the default values in the Default Values section.
  • Copy the two arrays from the example file and paste them into the field declarations in your file. Then open the model property editor, set Select Mode to Form Connection, select User Code, and enter the following:
    new DefaultTableModel(data, columnNames)

    Notice that the IDE has code completion in this editor. Once you get back to the source view, make sure to fix your imports to import DefaultTableModel. One major limitation here is that if you define the model in this way, you don't get to view it in the Design View. Not sure why that is, but I will investigate.

I did the latter, just because I'm too lazy to enter all of that stuff into the GUI when I can just copy and paste the two arrays.

Now where to put the rest of the code, namely the code that defines the selection model? Most of the examples have a createAndShowGUI method that's called from the main method to actually initialize and create the form. NetBeans does something similar in the initComponents method. This method is in a guarded blue block, which means you can't edit it manually. It is then called by in the JFrame constructor method, which is editable.

So for this example, the simplest thing is to let the IDE do its thing when initiating the code in the initComponents section, then add the code to further tune the component behavior in the constructor (or in a separate method that's then called by the constructor).

Before you start cutting and pasting, rename the JTable variable name to match what's in the example code by clicking the jTable1 node in the Inspector window, pressing F2, and typing table. Then copy the following code in bold into the constructor.

    public SimpleTableSelectionDemo() {
        initComponents();
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        if (ALLOW_ROW_SELECTION) { // true by default
            ListSelectionModel rowSM = table.getSelectionModel();
            rowSM.addListSelectionListener(new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent e) {
                    //Ignore extra messages.
                    if (e.getValueIsAdjusting()) return;

                    ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                    if (lsm.isSelectionEmpty()) {
                        System.out.println("No rows are selected.");
                    } else {
                        int selectedRow = lsm.getMinSelectionIndex();
                        System.out.println("Row " + selectedRow
                                           + " is now selected.");
                    }
                }
            });
        } else {
            table.setRowSelectionAllowed(false);
        }

        if (ALLOW_COLUMN_SELECTION) { // false by default
            if (ALLOW_ROW_SELECTION) {
                //We allow both row and column selection, which
                //implies that we \*really\* want to allow individual
                //cell selection.
                table.setCellSelectionEnabled(true);
            }
            table.setColumnSelectionAllowed(true);
            ListSelectionModel colSM =
                table.getColumnModel().getSelectionModel();
            colSM.addListSelectionListener(new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent e) {
                    //Ignore extra messages.
                    if (e.getValueIsAdjusting()) return;

                    ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                    if (lsm.isSelectionEmpty()) {
                        System.out.println("No columns are selected.");
                    } else {
                        int selectedCol = lsm.getMinSelectionIndex();
                        System.out.println("Column " + selectedCol
                                           + " is now selected.");
                    }
                }
            });
        }

        if (DEBUG) {
            table.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    printDebugData(table);
                }
            });
        }        
    }
 

Now add the boolean fields at the top of the file:

    private boolean DEBUG = false;
private boolean ALLOW_COLUMN_SELECTION = true;
private boolean ALLOW_ROW_SELECTION = true;

And add the printDebugData method somewhere in the file:

    private void printDebugData(JTable table) {
        int numRows = table.getRowCount();
        int numCols = table.getColumnCount();
        javax.swing.table.TableModel model = table.getModel();

        System.out.println("Value of data: ");
        for (int i=0; i < numRows; i++) {
            System.out.print("    row " + i + ":");
            for (int j=0; j < numCols; j++) {
                System.out.print("  " + model.getValueAt(i, j));
            }
            System.out.println();
        }
        System.out.println("--------------------------");
    }    

And run the file. Notice that you can select only rows and the Output Window says which row you selected. If you change the boolean values in ALLOW_COLUMN_SELECTION and ALLOW_ROW_SELECTION and run again, you can select cells, rows, or columns, and the Output Window tells you which one you've selected.

Here's the completed version of my file.

Thursday Apr 13, 2006

I Got a Cat...

In case you didn't know, I love cats. And so do these people:



Click to hear the cat song!

Wednesday Apr 12, 2006

Doing Your Own NetBeans Flash Demos

Been a while since I flogged but don't think I've been sitting on my keister the whole time, things around here have been hopping! Getting ready for JavaOne, looking at reorganizing the nb.org website docs and support section, working on a new and very cool Welcome Screen (more on that later)... Lots of stuff.

But one of the funner things we did was to put together some guidelines and templates for doing Flash demos. We took Vince's article about doing Wink demos and expanded it to provide full steps and a template for nice NetBeans-branded loading screen, controller (the thing at the bottom), intro and ending screen, and standard callouts and buttons. Check it out here:

  • http://www.netbeans.org/kb/articles/CreateWinkDemo.html
  • So get out there and start flogging!

    Friday Mar 24, 2006

    Walker - Texas Coder

    Been a busy week getting flogged and not doing much flogging, but this made me chuckle. Don't know if you've followed the sites that do random silly facts about Chuck Norris and Vin Diesel.

    Well, turns out Chuck Norris is a hardcore Java programmer as well.

    Thursday Mar 16, 2006

    Internationalizing a Matisse Form

    One of the coolest things about Matisse is that when you translate your program into another language, it doesn't get all screwed up because all of the components are grouped relative to each other with relative spacing provided by the look and feel. But how do you take a program with hard-coded display text and internationalize it?

    Marek Grummich answers this question in this latest installment in our continuation of Matisse articles. There are basically four things you can do (each of which Marek goes through, including Flash demos, of course):

    • Insert internationalized strings right in the GUI Builder as you create the form. To do this, click the ellipsis for the text property for a component, then select Resource Bundle in the Select Mode combo box and enter the properties file, key, and value (display text) for the string. View Demo
    • Insert an internationalized string in code. If you're working in the code view, and not in the GUI editor, just press Ctrl-Shift-J, specify the properties file, key, and value, and the IDE fills in the correct lookup code for you.

      View Demo

    • Internationalize an entire project at once. Right-click the Source Packages node and choose Tools > Internationalization > Internationalization Wizard. The wizard will go through and list all of the strings in the source files and suggest to replace them with key/value pairs in a properties file.

      Page 3 of the Internationalization wizard

    • Convert strings in a single file one at a time. Right-click the file in the Source Editor and choose Tools > Internationalization > Internationalize. This is best if you've got a small project or you know there are lots of strings that you don't want to internationalize. You cycle through all of strings one at a time and provide the key/value pairs for them.

      View Demo

    Another tip: If you know you've got a lot of strings that you don't want to internationalize, put a //NOI18N comment in each row that contains one of these Strings. Then go Tools > Options > Advanced Options > Editing > Internationalization and add //NOI18N to the regular expression in the I18n Search Format property. The IDE will automatically skip all these strings when you run internationalization commands.

    Then to run your project in a different locale, put a string like the following in your VM options:

    -Duser.language=es -Duser.country=ES

    And you get something like this:

    Hope everyone's enjoying the Matisse tutorials. Stay tuned for the next and most important one: Hooking up the Matisse form to a database. It's the hardest one so it takes the longest to write. Oh yeah, and regarding Matisse4Eclipse, using SWT to program a Swing app is like using a coal-powered generator to charge up your electric car. IMHO, it's kind of missing the point...

    Wednesday Mar 15, 2006

    Life After JBuilder

    I know, I know. You were happily using JBuilder, you've got all your personalized settings configured and your work flow down, you don't want to learn another tool. I feel your pain.

    But, the good folks at Borland have decided that JBuilder will soon be a thing of the past. So it's time to pick up the pieces and start thinking about life after JBuilder.

    Here's a first step:

    NetBeans IDE Guide for JBuilder Users

    A new article from Patrick Keegan, of NetBeans Field Guide fame, that shows you how to quickly port all of your JBuilder projects over to NetBeans. And once you get up-and-running, I bet you'll probably like NetBeans even more :-)

    Thursday Mar 09, 2006

    Museum Skipping in Amsterdam

    I'm back from a great vacation and don't feel like going throught the 957 emails I have. (We played a little game of The Price Is Right to see who could guess how many emails I had. Actually a thousand after six days vacation isn't that bad at all.) Went for three nights in Amsterdam, met up there with some friends that I haven't seen in ages. Then went down to Brussels for a few days, ate lots of mussels, drank lots of beer, and checked out a lot of Art Nouveau architecture.

    The weather wasn't very pleasant (a bit colder than Prague, but it was that wet cold that goes straight to the bone) but at least it didn't rain or snow on us much. And we spent most of our time in the museums anyways. I was most excited about the Van Goghs, since I'm reading a great biography on Vincent Van Gogh. (It's the first book I've ever read in Czech, it helps that it's an English book that was translated into Czech. Still I was a bit bummed when Bohdana flew through 30 pages in the time it takes me to read 3, but oh well.) I knew about the Dutch Masters and Rembrandt but wasn't too excited about them.

    Well, ho ho ho, to my surprise there's an incredible exhibition, for the 400th birthday of Rembrandt, that compares Rembrandt to Caravaggio. I absolutely love Caravaggio, and seeing all of his most famous pieces in person was worth braving the crowds. There's even one of a technical writer.

    But my favorites of Caravaggio were The Taking of Christ and Amour.

    But I also got a much greater appreciation for Rembrandt as well. I liked his mix of blurry outlines mixed with hyper-realist precision that give you both solid detail and the fluid feeling of motion at the time. And like Caravaggio, he's a master of dramatic lighting. As Mike pointed out, it always comes from the left!

    Oh yeah, and the Van Goghs were amazing too :-)

    About

    johnc

    Search

    Archives
    « April 2014
    SunMonTueWedThuFriSat
      
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
       
           
    Today