Wednesday May 09, 2007

Day 1 at JavaOne 07

Day 1 at JavaOne 07 was full of good stuff. There were a lot of announcements about FX, which sounds like an exciting new technology. I talked to a guy in the Erickson booth (You can't miss the booth, it is the only booth in the Sun section of the Pavilion where they aren't wearing the blue Sun shirts), and he did a good job of explaining how FX will change the way we use our phones.

My first session of the day was one on JRuby by Charles Nutter and Thomas Enebro (TS-9370). I have been hearing alot about Ruby, such as Craig making jMaki work with Ruby, so I decided I would use JavaOne as an opportunity to learn about this technology. Charles and Thomas gave an excellent introductory session for beginners like me. First they explained what Ruby was and why it was an improvement over Perl and JavaScript. For example:

  • It has a testing framework
  • It is more OO than JavaScript
  • It is easy to learn compared to Perl and JavaScript

On that last bullet, the woman next to me had switched from Perl and JavaScript to Ruby about a year ago, and she told me that it was indeed easy to learn and had also increased her productivity. She also agreed with their statement that the language was "addicting".

The duo then went on to explain why JRuby:

  • Faster (and will be even faster with future work)
  • More scalable
  • Unicode support
  • Will offer a compiler for even better performance
  • Better database support -- easy to pull in a new DB.

Gail recently helped with a NetBeans tutorial Creating a Ruby Weblog in 10 Minutes. I hope to give it a whirl when I get back from JavaOne. Also, there is this NetBeans day interview with Charles Nutter.

Another session I really enjoyed was David Botterill's Birds of a Feather talk about developing a real-world web application with the NetBeans IDE (TS-4092). He gave some fantastic tips and promises to follow up in detail on his web site. I highly recommend that you check out his slides when they become available and that you watch his blog for future entries.

I spent a lot of time at the NetBeans and Web 2.0 booths in the Pavilion. Sandip Chitale was showing how to use the new dynamic faces complib. We talked a bit about how to use fire transaction to do dynamic coordinated dropdowns. I hope to blog on that soon.

Next to the NetBeans booth is the jMaki booth. Carla was there showing how easy it is to use jMaki to add Ajax widgets to web applications. I never got a chance to talk to her because there was always a crowd. But I am attending all the jMaki sessions that I can.

--

Tuesday Mar 06, 2007

Daylight Savings Time Patch for the JDK Bundled With the Sun Java Studio Creator IDE

The start and stop dates for daylight savings time in the United States and most of Canada have changed. To learn how to patch the JDK that is bundled with the Sun Java Studio Creator IDE so that it can handle the changed dates, see this FAQ.

Monday Jan 08, 2007

JasperReports Tutorial: Missing Record Bug

A few customers have pointed out a bug in the Generating Reports and PDFs From a Web Application tutorial. I have to admit that I am somewhat embarrased that I never noticed that the first record is missing from the reports.

I am trying to get the fix pushed out this week. In the meantime, for those who are using code from the tutorial, you should know that you need to either call beforeFirst() or execute() on the rowset before passing the rowset to the JRResultSetDataSource constructor.

Tuesday Dec 19, 2006

New Web UI Components Category

Now that we blog about both the Sun Java Studio Creator IDE and the NetBeans Visual Web Pack, we needed a place to put blogs that apply to both products. So, if you have only been reading the topics in the Sun Java Studio Creator category, you might want to add the Web UI Components category to your reading list as well (and you should probably add Ajax too).

Sunday Dec 10, 2006

Using the Tab Set for Page Navigation

In our Tabbing Thru the Tulips entry, we show how to use a Tab Set component in a Page Fragment for site navigation. I am happy to say that a Sun Java Studio Creator IDE user has designed a different solution, which better addresses real-world scenarios. He has been kind enough to post his solution on the community java.net wiki for the IDE. You can read his write up at http://wiki.java.net/bin/view/Javatools/MenuTabSetExample.

Thanks Mark (aka Yossarian aka Khumalo).

Tuesday Dec 05, 2006

When a Web Server is All You Need

If you are developing a web application using the Sun Java Studio Creator IDE, and the application does not use Enterprise JavaBeans technology, you might not really need the overhead of a full blown application server. If that is a case, consider using the Sun Java System Web Server 6.1 for your development phase. While it is true that you can war up your web application and deploy it to an application or servlet container, as shown in our deployment tutorials, the IDE also offers a one-step menu item, Deploy to Remote Server, that deploys your project to an instance of the Sun Java System Web Server and runs the web application in your browser. You might find the test-modify-redeploy cycle a bit faster and the memory consumption somewhat lower.

After downloading and installing the web server (don't forget to write down the User Id and Password that you entered), copy the following files to the web server's bin/https/jar folder.

  • If you plan to use web services, copy dom.jar and xercesImpl.jar from ide_install_dir//SunAppServer8/lib.

  • If you plan to use databases, copy ide_install_dir/SunAppServer8/lib/driveradapter.jar and then add the necessary driver files for your database server to the jar folder as well.

    Note: You can copy ide_install_dir/SunAppServer8/derby/lib/derbyclient.jar, but you cannot copy the other JDBC drivers because they are locked, so you need to obtain other drivers from the OEMs.

Start the Admin Server and open the web server's Admin Console typically, http://localhost:8888) in your browser. Select a web server (when you first install, there is just one) and click Manage.

  1. Click the Java tab.

  2. In the sidebar, click JVM Path Settings.

  3. If you will be using web services, enter the following in the Classpath Suffix field, using OS specific path separators and no line breaks:
    webserver_install_dir/bin/https/jar/dom.jar
    webserver_install_dir/bin/https/jar/xercesImpl.jar
    
    For example, on a Windows system, enter:
    C:/Sun/WebServer6.1/bin/https/jar/driveradapter.jar;C:/Sun/WebServer6.1/bin/https/jar/derbyclient.jar
    
  4. If you will be using databases, enter the following in the Classpath Suffix field, using OS specific path separators and no line breaks:
    webserver_install_dir/bin/https/jar/driveradapter.jar
    webserver_install_dir/bin/https/jar/yourdatabasedriver.jar
    
  5. Click OK in the JVM Path Settings tab.

  6. Click the Apply button in the top right corner of the Admin Console, and then click the Apply Changes button.

    When you applied the changes, the console should start the web server. If the web server was not started, click Manage and click Server On.

Now you are ready to set up the web server in the IDE.

  1. In the Servers window in the IDE, right-click Remote Deployment Servers, and choose Add Remote Server.

  2. For Server Type, choose Sun Java System WebServer 6.1.

  3. Set the Admin Host to localhost, set the Admin Port to 8888, and set the Username and Password to the values that you entered when you installed the web server (the ones you use when you start the Admin Console).

  4. Select the radio button for Data Sources Configured Automatically by JSCreator.

  5. Click OK. Hopefully, the node is added with a green badge.

That takes care of the setup. To test a web application using the Sun Java System Web Server, right-click the web application's node in the Projects window and choose Deploy to Remote Server > your web server from the pop-up menu.

Monday Nov 20, 2006

Using JasperReports to Generate PDF and Reports in Web Applications

We just published a new tutorial today on how to use the JasperReports framework in a web application built using the Sun Java Studio Creator IDE. In this tutorial, you create a web application that displays and prints information from a travel database. The web application lets you view a trip report in either HTML format or PDF format.

Some interesting parts of this tutorial are that you use a managed bean instead of a servlet to generate the report, you add an entry to the build.xml file to compile the reports for you, and you reuse your dataprovider's rowset query for the report.


Check it out at http://developers.sun.com/prodtech/javatools/jscreator/learning/tutorials/2/reports.html.

Wednesday Nov 15, 2006

Tutorial Rate and Review Box Broken

At the bottom of each of our Sun Java Studio Creator tutorials is a Rate and Review box where you can rate the tutorial and submit comments or questions. The responses that you have sent to us are extremely valuable. We have made many improvements based on the feedback that you send to us using the Rate and Review box.

Unfortunately, this mechanism broke about one month ago and the Rate and Review responses are going into a black hole, never to see the light of day. After repeated requests to fix this, we finally got word that they are not going to fix it. Eventually, they will move to some other mechanism. When that happens, we will let you know. In the meantime, don't bother with the Rate and Review box. If you have suggestions, problems, or questions, you can submit them to us by going ot http://developers.sun.com/prodtech/javatools/jscreator/learning/tutorials/index.jsp and clicking on the link to the feedback form.

Friday Oct 27, 2006

Workaround for Dynamic Trees

There have been many posts on the Sun Java Studio Creator IDE forum from people having trouble with using getSelected() or getCookieSelectedTreeNode() when building dynamic trees. We have had the same problems while writing our database tree tutorial. I have filed some bugs on their behalf as well as ours, but we won't see fixes in the near future. In a nutshell, you can't tell what node was selected if the user has cookies turned off, and if there are stale cookies around, getCookieSelectedTreeNode might serve up that stale cookie instead of the actual node selected.

So, in the meantime, I came up with this workaournd. What we do in the database tree tutorial (which is still work in progress) is to pass the selected value in a URL.

Here is the modified code. Notice the setUrl()

part in bold.

 
    public void prerender() {
        // If the Request Bean's personId is set, then
        // we just came back from the Trip page
        // and had displayed a selected trip.
        // We use the personId later to determine whether
        // to expand a person's node
        Integer expandedPersonId = getRequestBean1().getPersonId();
        try {
            // Set up the variables we will need
            Integer currentPersonId = new Integer(-1);
            // If nbrChildren is not 0 then this is a
            // postback and we have our tree already
            int nbrChildren = displayTree.getChildCount();
            
            if (nbrChildren == 0) {
                // List of outer (person) nodes
                List outerChildren = displayTree.getChildren();
                // Erase previous contents
                outerChildren.clear();
                // List of inner (trip) nodes
                List innerChildren = null;
                // Execute the SQL query
                tripDataProvider.refresh();
                // Iterate over the rows of the result set.
                // Every time we encounter a new person, add first level node.
                // Add second level trip nodes to the parent person node.
                boolean hasNext = tripDataProvider.cursorFirst();
                while (hasNext) {
                    Integer newPersonId =
                            (Integer) tripDataProvider.getValue(
                            "TRIP.PERSONID");
                    if (!newPersonId.equals(currentPersonId)) {
                        currentPersonId = newPersonId;
                        TreeNode personNode = new TreeNode();
                        personNode.setId("person" + newPersonId.toString());
                        personNode.setText(
                                (String)tripDataProvider.getValue(
                                "PERSON.NAME"));
                        // If the request bean passed a person id,
                        // expand that person's node
                        personNode.setExpanded(newPersonId.equals
                                (expandedPersonId));
                        outerChildren.add(personNode);
                        innerChildren = personNode.getChildren();
                    }
                    
                    // Create a new trip node
                    TreeNode tripNode = new TreeNode();
                    tripNode.setId("trip" +
                            tripDataProvider.getValue("TRIP.TRIPID").toString());
                    tripNode.setText(
                            tripDataProvider.getValue("TRIP.DEPDATE").toString());
                    tripNode.setUrl("/faces/Trip.jsp?tripId=" +
                            tripDataProvider.getValue("TRIP.TRIPID").toString());
                    innerChildren.add(tripNode);
                    hasNext = tripDataProvider.cursorNext();
                }
            }
            
        } catch (Exception ex) {
            log("Exception gathering tree data", ex);
            error("Exception gathering tree data: " + ex);
        } 
     }

Then, in the destination page, we add the following code to pick up the passed parameter.

 


    public void prerender() {

        // Get the person id from the request parameters
        String parmTripId = (String)
        getExternalContext().getRequestParameterMap().get("tripId");
        
        if (parmTripId != null) {
            Integer tripId = new Integer(parmTripId);
            try {
                getSessionBean1().getTripRowSet1().setObject(1, tripId);
                tripDataProvider1.refresh();
            } catch (Exception e) {
                error("Cannot display trip " + tripId);
                log("Cannot display trip " + tripId, e);
            }
        }else {
            error("No trip id specified.");
        }
     }

Wednesday Oct 04, 2006

Customer Written Tutorial on Using iText From Java Studio Creator IDE

Many people have been asking in the forum and in requests sent using our tutorial docs feedback form how to generate reports, such as PDF, from web apps built using Java Studio Creator IDE. I have been working on a JasperReports tutorial for quite some time, and have hopes to get it published in a couple of weeks. One of our customers Sander beat me to the punch. He wrote his own tutorial and he makes it available from his company's website. Thanks Sander!

Thursday Sep 21, 2006

Using Servlets in the Java Studio Creator IDE

I am working on a tutorial on how to use JasperReports in JSF web applications. At first, like most examples out there, I built a servlet and called the servlet from my web page. I eventually figured out that it is quicker and easier to use a managed bean, and took that route instead.

However, I do see a lot of posts in the forum asking how to use servlets in JSF web applications built using the IDE, so here is what I learned.

  1. Make the servlet and put it in the web applications source package structure or add it to the library node. In this example, I called the servlet ReportGenerator.

  2. Make a mapping for the servlet. To do so, go to the Files window, expand web, expand WEB-INF, and double-click web.xml to open the xml editor.

  3. Click the Servlets button in the editing toolbar and click Add Servlet Element.

  4. Set the Servlet Name to whatever you choose (I used ReportGenerator).

  5. For the Servlet Class, browse to the source for your servlet (or type in the fully-qualified class name if using a library).

  6. Type a URL Pattern. This is how you will invoke the servlet from your web page. I used /makeReport. One thing to notice is that you need to prepend a forward slash here but you don't include the forward slash when you use it in a redirect, as you will see later. Click OK.

  7. Now you might think that you next bring up the Page Navigation editor to add a navigation mapping for makeReport. But that is not how you do it. From everything that I have read, JSF navigation entries are for navigation from a JSF view to a JSF view. So, what I did was to use a redirect, as shown in the following code:

     
        public String button1_action() {
            try {
            FacesContext facesContext = getFacesContext();
            HttpServletResponse response = 
    		(HttpServletResponse) facesContext.getExternalContext().getResponse();
            response.sendRedirect("makeReport");
            facesContext.responseComplete();
            } catch (Exception e) {
                log(e.getMessage());
                error(e.getMessage());
            }
            return null;
        }
    	


    Note that after redirecting the request, I send a responseComplete. This is extremely important. It is like passing the baton and notifying that you are dropping out of the lifecycle. If you don't complete the response, then you will get this exception:

    Exception Details: java.lang.IllegalStateException Cannot forward after response has been committed

  8. Alternatively, if you want a link instead of an action handler, you can add a link component and set it's url property to /faces + your pattern (this time include the forward slash). In my case, I set the url property to /faces/makeReport.

Thursday Sep 07, 2006

Dynamically Building a Tree from Database Data

Here is a mini tutorial that teaches you how to dynamically build a tree structure from data in a database. You populate the first-level nodes in the Tree with names from a database and the second-level nodes with the trip dates for that person.

Notes: Due to cookie problems, it is hard to tell which node the user selects. See http://blogs.sun.com/divas/entry/workaround_for_dynamic_trees for a workaround

Events related to tree node selection do not work correctly in portlets because the Tree component uses cookies to pass the selected node id back and forth, and cookies are not correctly handled by the portlet container.

Designing the Home Page

You begin by building a home page that includes the Tree component and the TRIP database table. The following figure shows the page.

 
Figure 1: Page Design
Figure 1: Page Design
 
  1. Create a new project and name it DatabaseTree.

  2. From the Basic section of the Palette, drag a Tree component onto the Page, type Travel Information, and press Enter. In the Properties window, set the id property to displayTree and the clientSide property to True.

    When clientSide is True, every child node (expanded or not) is sent to the client, but is not made visible unless the parent node is expanded. When clientSide is False, only the child nodes of the expanded parent nodes are rendered.

  3. Select Tree Node 1, right-click, and choose Delete from the pop-up menu.

    For this application, you do not need the initial tree node that the IDE creates because you are populating the tree programmatically. If you do not remove the node, the values set in the JSP tag attributes take precedence over the runtime settings, and the page displays the node.

  4. Drag a Message Group component from the Palette onto an out-of-the-way place on the page, such as the upper-right corner of the page.

Connecting to the Database

Next, you connect the page with a database table in the Travel data source. You then use the Query Editor to modify the SQL query used to retrieve the data so that the traveler names appear in alphabetical order and the travel dates appear in chronological order.

  1. Open the Servers window and ensure that the Bundled Database Server is running.

    The node's status icon and tooltip indicate whether the server is running. If the Bundled Database Server is not running, right-click the Bundled Database Server node and choose Start Bundled Database from the pop-up menu.

  2. In the Servers Window, expand Data Sources > Travel > Tables. Drag the TRIP node onto the Visual Designer.

    The Outline window shows a tripDataProvider node in the Page1 section and a tripRowSet node in the SessionBean1 section.

  3. In the Outline window, right-click the tripRowSet node and choose Edit SQL Statement.

    The Query Editor appears in the editing area, with a a TRIP table diagram.

  4. From the Servers window, drag the Travel > Tables > PERSON node and drop it next to the Trip table diagram in the Query Editor, as shown in Figure 2.

    Another table diagram appears with a link, or join, between the two table diagrams.

  5. In the PERSON table, clear the checkbox for PERSONID.

  6. In the Design Grid of the Query Editor, find the NAME row for the TRAVEL.PERSON table. Click in the Sort Type cell and choose Ascending from the drop-down list.

    This action sorts the names in the database table alphabetically by last name.

  7. Find the DEPDATE row for the TRAVEL.TRIP table. Click in the Sort Type cell and choose Ascending from the drop-down list.

    This action sorts the trip dates from earliest date to latest date. The following figure shows the Query Editor.
     
    Figure 2: Query Editor
    Figure 2 : Query Editor

Building the Tree From the Database Table

Now you add code to the prerender() method to dynamically build the Tree component from the TRIP and PERSON database tables.

  1. Open Page1 in the Java Editor and scroll to the prerender method. Replace the body of the prerender method with the following code shown in bold.
     
    Code Sample 1: prerender method for Page1
       public void prerender() {
             try {
                // Set up the variables we will need
                Integer currentPersonId = new Integer(-1);
                // If nbrChildren is not 0 then this is a
                // postback and we have our tree already
                int nbrChildren = displayTree.getChildCount();
                if (nbrChildren == 0) {
                    // List of outer (person) nodes
                    List outerChildren = displayTree.getChildren();
                    // Erase previous contents
                    outerChildren.clear();
                    // List of inner (trip) nodes
                    List innerChildren = null;
                    // Execute the SQL query
                    tripDataProvider.refresh();
                    // Iterate over the rows of the result set.
                    // Every time we encounter a new person, add first level node.
                    // Add second level trip nodes to the parent person node.
                    boolean hasNext = tripDataProvider.cursorFirst();
                    while (hasNext) {
                        Integer newPersonId =
                                (Integer) tripDataProvider.getValue(
                                "TRIP.PERSONID");
                        if (!newPersonId.equals(currentPersonId)) {
                            currentPersonId = newPersonId;
                            TreeNode personNode = new TreeNode();
                            personNode.setId("person" + newPersonId.toString());
                            personNode.setText(
                                    (String)tripDataProvider.getValue(
                                    "PERSON.NAME"));
                            outerChildren.add(personNode);
                            innerChildren = personNode.getChildren();
                        }
                        
                        // Create a new trip node
                        TreeNode tripNode = new TreeNode();
                        tripNode.setId("trip" +
                                tripDataProvider.getValue(
                                "TRIP.TRIPID").toString());
                        tripNode.setText(
                                tripDataProvider.getValue(
                                "TRIP.DEPDATE").toString());
                        // Set "action" property to use for navigation
                        tripNode.setAction(
                                getApplication().createMethodBinding
                                ("#{Page1.tripNode_action}", null));
                        innerChildren.add(tripNode);
                        hasNext = tripDataProvider.cursorNext();
                    }
                }
                
            } catch (Exception ex) {
                log("Exception gathering tree data", ex);
                error("Exception gathering tree data: " + ex);
            }    
    
         }
              
     
    This code reads the trip records, which are ordered by the personId. For every personId, the code creates a new level-one node in the Tree. The code then creates a level-two node (nested node) for every trip associated with that personId.

  2. Place the cursor in the Java Editor and press Alt-Shift-F to fix the class not found errors. In the Fix Imports dialog box, ensure that java.util.List appears in the Fully Qualified Name field and click OK.

  3. Run the project.

    The web browser opens and displays a Tree component with each first-level node showing the name of a person. The top-level node is expanded to show the travel dates for that person. Note that the names appear alphabetically by last name and the dates appear in chronological order, as shown in the following figure. Continue exploring the application by expanding and contracting the first-level nodes in the Tree.
     
    Figure 3: Dynamic Tree Node
    Figure 3: Dynamic Tree Node

Wednesday Aug 30, 2006

Adding a Popup Window to a Java Studio Creator Web Page

Here is a mini-tutorial for creating a Popup window for the user to lookup values. One scenario that you might use this for is when the page visitor needs more information then can be displayed in a drop-down list.

Note: The original post of this blog entry had code that did not work in Internet Explorer. Escritorioooo posted a solution to the forum and I updated the code using Escritorioooo's solution. Thanks Escritorioooo!

  1. Create a project or open an existing one.

  2. Add a page named Popup.

  3. Add a Table component to the page.

  4. Drag VIR > Tables > State from the Servers window and drop it on the page.

  5. Right-click the Table component and choose Table Layout from the pop-up menu.

  6. In the column for the STATE.STATEID database field, set the Component Type to Hyperlink, and click OK.

  7. Select the Hyperlink component so that its properties appear in the Properties window.

  8. Set the value for the onClick property to doSave('#{currentRow.value['STATE.STATEID']}')

    (I got the value to pass to doSave() from the Value Expression in the Table Layout dialog).

  9. Click JSP in the editing toolbar to view the JavaServer Pages script.

  10. Add the following code shown in bold just under the opening tag for ui:body:

     
    <ui:body binding="#{Popup.body1}" id="body1" style="-rave-layout: grid">
    <script><![CDATA[
    function doSave(val) {
      window.opener.setVal(val);
      window.close();
    }]]></script>
    


    The Popup page is now ready for use by another page.

  11. Create a new page called Form1. Make it be the start page.

  12. Drop a Hyperlink component on the page and set the text property to State Code.

  13. Set the url property to /faces/Popup.jsp.

  14. Set the onClick property to doPopup("form1:textField1")

    Note: Here you are passing the id of the field to fill with the selected value. Determining the id can be tricky. For example, if you set the label property of the Text Field component, the id changes to form1:textField1_field.

    To determine what to use for the id, right-click in the page and choose View in Browser. When the page displays in the browser, choose View Source from the appropriate browser menu and look for the id setting for the component's <input> tag.

  15. Click the ... button for the target property to open the target property editor.

  16. In the property editor, click New and set both the Display and Value to popup. Click in some field and check that both values stuck. Then click OK.

    Later you add script to open a window named popup, and this setting causes the Popup.jsp page to display in that window.

  17. If the target property value is still blank, select popup from the combobox for that property.

  18. Drag a Text Field component and drop it under the Hyperlink component. By default, the component's id should be textField1. If not, change the id passed to doPopup() in step 14 to match. Use the View in Browser trick mentioned in Step 14 to determine the value to pass.

  19. Click JSP in the editing toolbar to view the JavaServer Pages script.

  20. Add the following code shown in bold just under the opening tag for ui:body:

     
    <ui:body binding="#{Popup.body1}" id="body1" style="-rave-layout: grid">
    <script><![CDATA[
    function doPopup(destination) {
      popup = window.open("", "popup", 
        "height=300,width=200,toolbar=no,menubar=no,scrollbars=yes");
        destinationElement=document.getElementById(destination);
      popup.focus();
    }
    
    function setVal(val){
      destinationElement.value=val;
    }]]></script>
    


    This script adds an instance field name openerDestinationElement to the popup window. The script for the Popup page uses openerDestinationElement to get to the Text Field component on the Form1 page.

  21. Run the project. Click State Code to open the popup window. Click a state code to select the code, close the popup window, and populate the text field.

Friday Aug 25, 2006

Better Performance - We Listened

As Java Studio Creator IDE users began building large web applications, we started hearing requests for better IDE performance. So the Creator team decided that the right thing to do was to give performance improvement a top priority and assigned a Performance Tiger team to produce results. As part of the effort, the Tiger team worked directly with customers to identify problems and to verify the performance improvements. The Quality Engineering team was an integral part of this effort, designing tests based on the customer applications, measuring results (see the above chart), and ensuring that that there were no regressions.

Most of the customer applications that were used for testing had over 50 pages. The Quality Engineers couldn't even open many of the applications in the IDE without first changing the default memory setting in the creator.conf file from -J-Xmx384m to -J-Xmx512m or more. One of the customer applications had over 175 pages.

I want to mention that the Performance Tiger team is not dumping and running. They want your feedback. If you are still having performance problems, please post your issues to the forum. Of course, if you are seeing significant improvements, they would probably like to hear about that too.

You can download today's hot fix release from the update center. To learn how to use the update center, go to the Updates web page.

I would like to say "well done" to the Performance Tiger Team, Quality Engineering, Release Engineering, and the customers who worked with us.

Note: for more improvement stats, see Sakthi's blog.

Friday Aug 18, 2006

Rate and Review Comments are Broken

If you have submitted any comments using the Rate and Review Comment box at the bottom of our tutorials, please know that the submissions are not getting to us. Apparently, the mechanism has been broken for a few weeks.

We apologize to those of you who have written to us using the comment box and have not received a reply.

They have not told us when this will be fixed.

Thursday Aug 17, 2006

New Hibernate Tutorial Using ObjectListDataProvider

Last night we posted our newest tutorial, Using Hibernate With the Sun Java Studio Creator IDE. This tutorial shows the essential steps necessary for adding a Hibernate framework to your project, as well as shows now to display the query results in a DropDown List component and a Table component.

This tutorial is not only helpful for Hibernate users, it is also helpful for anyone who is using a database for which compliant JDBC drivers are not available. You can use the concepts shown here to learn how to use the ObjectListDataProvider and Option arrays to feed the data from your result sets to the web application.

Note: NetBeans has a plug-in to generate the Hibernate persistence classes. You can read about it here and here.

Wednesday Jun 21, 2006

Saving Uploaded Files Uploaded by the File Upload Component

The Java Studio Creator File Upload tutorial shows how to upload a file to the web application's /resources/images folder. But, what if you want to save the uploaded files elsewhere? Here are some alternatives.

A different folder in the web application.You can put the images in any directory in the web application (that is, any directory under the web application's web directory). For example, you can create an upload/images subfolder under web and use the following code to store the images there:

           String realPath =
              theApplicationsServletContext.getRealPath
              ("/upload/images");
           File file = new File(realPath + File.separatorChar +
              justFileName);

One thing you need to be careful about when putting the uploaded files in the web application, is that anyone can access the files by URL, such as http://localhost:29080/MyWebApplication/faces/upload/images/myPicture.gif.

A known directory on the server. If you want to store the images somewhere else on the server, you can use code like the following:

           File file = new File("C:/upload/images" + File.separatorChar +
              justFileName);          
           uploadedFile.write(file);

If you plan to deploy the application to different servers, you might want to use code like the following to ensure that the upload directory exists:

                File dir = new File("C:/upload/images");
                if (! dir.exists()) dir.mkdirs();
                File file = new File(dir.getCanonicalPath() + File.separatorChar +
                        justFileName);
                uploadedFile.write(file);

For more information about the File class, see http://java.sun.com/j2se/1.3/docs/api/java/io/File.html.

An as yet unknown directory. An alternative is to put the directory path in the deployment descriptor, so that you can change the location dynamically.

  1. In the Files window, expand web and expand WEB-INF. Double-click web.xml to open it.

  2. Click the Context Parameter Add button, set the following values, and click OK.

    Param Name: uploadDirectory (or whatever you want to name it)
    Param Value: C:/upload/images (or whatever your path is)


  3. Close and save the web.xml file.

  4. Use the following code:
                    String uploadDirectory =
                            getExternalContext().getInitParameter("uploadDirectory");
                    File file = new File(uploadDirectory +
                            File.separatorChar +
                            justFileName);
                    uploadedFile.write(file);
    

Thursday Jun 15, 2006

Table Component Sample Project

After all these months, I am finally making progress on the tutorial for the Table component. It might be a long time before I document all the steps and get the tutorial through quality assurance, editorial, and production processes. So, for those who can learn by examining code, I have decided to post the project that you build by completing the tutorial.

Here are some of the project's features:

  • Gets the data from an ObjectListDataProvider
  • Has dropdown lists, checkboxes, and buttons in the table
  • Has input fields that are not associated with the underlying data provider, so the input needs to be stored separately
  • Calculates totals from the selected table rows
  • Has dynamic footer information

Of course, everything I learned, I learned from Winston. He has posted lots of good Table component tips in his blog, so be sure to go there for advanced Table component information.

You can download the project zip from here.

Important Note: After you first open the project, build the project, then close and re-open the project. Otherwise you can get errors and the design-time mechanisms might not see the FoodListDataProvider.

Wednesday Jun 14, 2006

Read the Tutorials in PDF Format

You asked--we delivered. The PDF versions of the Java Studio Creator tutorials are here! Cindy Church converted all of the 44 published tutorials and compressed them into ZIP files that align with the categories on the tutorials index page. For example, the GetStarted.zip file contains: Getting Started With Sun Java Studio Creator, Developing a Web Application, and Using the Java Editor

The hyperlinks work within each PDF file. Cindy added page numbers and formatted the files with wide margins so you can add the printed document to a binder or write notes in the margins. We thank our PDF early reviewers for their comments on the early iterations of our PDF files. If you have any questions or comments about the PDF files, please use our Feedback Form

Friday Jun 09, 2006

June Tutorial Update

We have lots of good things going on with the Sun Java Studio Creator tutorials

Tutorials International

In addition to English, the Java Studio Creator tutorials are available in the following languages:

We also have the two new tutorials on how to create an internationalized applications in the Java Studio Creator IDE.

PDFs and Videos

Our co-worker, Cindy Church, has been diligently creating PDF versions of our 43 tutorials. The PDFs will be available soon on the tutorials page. For those of you who did early reviews of the PDF versions, we appreciate your input and we tried to implement as many of your suggestions that we could.

In addition, we've had requests for video versions of our tutorials. If this is something you would like, please send us your suggestions via our Feedback Form.

We're Listening

You might have heard from us this week. We put a lot of effort into responding to the comments in the Rate and Review boxes on the tutorials. We apologize if our responses were a little late--our co-worker, Dustin, who collects this information, was out of the office for several weeks on his honeymoon. Chris responded to comments on the Getting Started and Database tutorials and Gail responded to comments on the AJAX tutorials and other component tutorials. One common thread we see is that users get an error when they try to connect to a database. In some cases this is an easy fix: in the Servers window, right-click Bundled Database Server and choose Start Bundled Database. We will add a paragraph on how to start the database server when we update the tutorials.

More Tutorials and Code Snippets Coming

Chris' mini jMaki tutorial has been very successful and now she's head down working on a tutorial on the Table component. She'll have a sample Table application available in this weblog next week. Gail is nearing completion of a tutorial on the AJAX Rating tutorial--with lots of help from the component's author, Matthew Bohm.

Craig McClanahan has supplied us with a project that loads the contents of a tree dynamically from a database, which we're turning into a tutorial. This particular project came about because one of the customers that Craig was talking to was doing a proof of concept application. So, Craig built an early prototype of this application while on an airplane on his way home from the visit, and then offered it us as a subject for a tutorial. Lucky for us!

Wednesday May 24, 2006

Diva #2 goes to JavaOne 2006

I am finally recuperated from JavaOne. What a blast. Not only was it a great opportunity to meet people, but I have stuffed my brain with a lot of new knowledge, as well as a good idea of what I need to learn going forward. The two most important concepts that I need to start learning about, in addition to JSF 1.2 of course, are injections and annotations. I was relieved to learn that my peers on the NetBeans team have nicely summed these concepts up at http://www.netbeans.org/kb/55/javaee-intro.html. So, if these terms are new to you as well, check it out.

I attended lots of AJAX sessions and found it interesting all the different ways people are tackling the I-really-don't-want-to-work-with-JavaScript problem. Bruce Johnson and Joel Webber, from Google, have created a way to code in Java and compile into JavaScript. You can get this from http://code.google.com/. Greg Murray has developed jMaki, a JavaScript wrapper tag set. If you are interested in AJAXizing your web app, check out his blog. The "new" words of the day, for me, were mashup and smashup (a mashup involving a Swing application).

Speaking of AJAX, Jayashri, Matthew, and I developed and presented a hands-on lab that shows how to use AJAX in Sun Java Studio Creator projects. It was such a hot topic that we had to present the lab twice (picture above -- that's me at the podium). You can get ahold of this lab at http://www.javapassion.com/handsonlabs/. Look for LAB-5655.

I was really glad that I attended the Extreme Web Caching session presented by Jason Hunter. His presentation offered great advice on cajoling the browsers to cache what needs to be cached and not cache that which should not. If you are concerned about bandwith, take a look at http://www.mnot.net/.

Saturday May 20, 2006

New Internationalization and Deployment Tutorials

We have three new tutorials to help you learn about internationalization, localization, and deployment:

  • Understanding Internationalization provides background information for developing an internationalized application. This tutorial also provides an example of localizing an application for a specific locale.

  • Creating an Internationalized Application provides step-by-step instructions for building an internationalized application The application described in this tutorial enables a client browser to set the application's locale and character encoding at runtime. This capability is useful when your application must support multiple languages, different encodings of the same language, or legacy encodings.

  • Deploying to Sun Java System Web Server 6.1 describes how to deploy a web application with either a web service or a datasource to a stand-alone Sun Java System Web Server 6.1. Thanks to Roman Mostyka and Krystyna Polomski in Quality Engineering for making this tutorial possible.

We're planning future tutorials on components, AJAX, and, database access. Send your suggestions to us via our Feedback Form

.

Tuesday May 02, 2006

Tutorials Update

Today you'll notice a slight change in the look of the tutorials. The stamp on the right-side of the tutorials has been changed to:

stamp showing that tutorials work for both
Creator 2 and Creator 2 Update 1  

This stamp indicates that our tutorials work for both the Java Studio Creator 2 IDE and the Java Studio Creator 2 Update 1 IDE, which is now available on the Sun Developer Network (SDN) at http://developers.sun.com/prodtech/javatools/jscreator/downloads/updates/index.html.

Thursday Apr 20, 2006

New Tutorial on Creating Bookmarkable URLs

If you have a page that you want users to be able to bookmark, and the page requires parameters, you can use the URL to pass the parameters. Our new tutorial, Creating Bookmarkable URLs shows how to dynamically create a URL that includes the parameters and how to access the parameters from the bookmarkable page. Many thanks to Lark Fitzgerald and Craig McClanahan for doing the legwork on this tutorial and for all their technical advice.

You can send us comments on this or any other tutorial or technical article by using the Rate and Review box at the end of the tutorial or technical article (see Figure 1). We read these comments on a weekly basis and add information or make other adjustments to the tutorials based on your feedback.

Figure 1: Rate and Review Comment Box
Figure 1: Rate and Review Comment Box

Thursday Mar 30, 2006

Three Tutorials Available in PDF

Good news! Today we posted on our tutorials landing page a PDF file that includes our three Getting Started tutorials:

  • Getting Started With Java Studio Creator
  • Developing a Web Application
  • Using the Java Code Editor

This PDF shows that we are on are way to meet your requests for PDF versions of the tutorials. We plan to create a PDF for each category of tutorials that appears on the tutorials index page.

If you have trouble printing the PDF file, make sure that you have the latest version of the Adobe Acrobat Reader.

We are interested in your feedback so please let us know if this PDF meets your needs and provide suggestions for improvement. Send comments to us via our Feedback Form.

Monday Mar 27, 2006

Using Checkboxes in a Table Component

Here is a one way to add a checkbox column to a table and determine which checkboxes have been checked.

  1. Add a property named selectedRows of type java.util.Set to SessionBean1.

  2. Add the following code to the init() property in SessionBean1.
    
    selectedRows = new HashSet();
    
    
  3. Add a property named selected of type boolean to SessionBean1.

  4. Change the getter and setter to the following code:
    
       /\*\*
         \* Getter for property selected
         \* @return true if checkbox in current row is selected
         \*/
        public boolean isSelected() {
            TableRowDataProvider rowData = (TableRowDataProvider) getBean("currentRow");
            if (rowData == null) {
                return false;
            } else {
                String rowId = rowData.getTableRow().getRowId();
                if (this.getSelectedRows().contains(rowId)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        
        /\*\*
         \* Setter for property selected.
         \* @param boolean; true if checkbox is selected, false if checkbox is cleared.
         \*/
        public void setSelected(boolean b) {
            TableRowDataProvider rowData = (TableRowDataProvider) getBean("currentRow");
            if (rowData != null) {
                String rowId = rowData.getTableRow().getRowId();
                if (b) {
                    this.getSelectedRows().add(rowId);
                } else {
                    this.getSelectedRows().remove(rowId);
                }
            }
        }
    
    
  5. Bind the Checkbox component's selected property to SessionBean1 > selected.

  6. Use code like the following to determine which checkboxes are selected.
    
    Iterator rows = getSessionBean1().getSelectedRows().iterator();
    while (rows.hasNext()) {
        String rowId = (String) rows.next();
        RowKey rowKey = <your table's data provider>.getRowKey(rowId);
        ... use the row key to access the data in the data provider
    }
    
    

Thursday Mar 23, 2006

New Themes and Project Templates Tutorials

We have two new tutorials to help you in creating pages. These tutorials include:

  • Creating a Theme. This much-awaited tutorial, written by Cindy Church and Krys Polomski, teaches you how to:

    • Identify the parts of a theme file, which includes a MANIFEST.MF file, properties files, and resource files
    • Create a new theme
    • Add the new theme to the Themes library in the IDE
    • Apply the new theme to your project

  • Using Project Templates. This tutorial shows you two ways to save a project as a template and also shows you how to open a new project that uses the project template that you created. We would like to thank our Creator online help writer, Paul Fussell, for helping with this tutorial.

We wrote these tutorials based on your feedback, so keep the ideas coming. You can submit an idea for a tutorial via our Feedback Form.

Tuesday Mar 21, 2006

Updated Understanding Scopes and Managed Beans Tutorial

Since we published the Understand Scopes and Managed Beans tutorial, we have received a customer comments about this tutorial. People were telling us that the tutorial was putting a method in the session bean, while it should be in the application bean. Well, the tutorial was correct, so it was obvious that the tutorial was confusing people. So, we rewrote the tutorial, with hopefully a less confusing example. We really appreciate your feedback. It helps to know what is working, so that we can continue along those lines, and what isn't working, so that we can fix it. Check out the updated version and let us know what you think.

Friday Mar 17, 2006

Iterating Through Table Data

Let's say that you want to put a footer in a column to show the column's total. To do so, you could code like the following in a property's getter method and bind the column's footer to the getter method.

        int total = 0;
        try {
            employeeDataProvider.cursorFirst();
            do {
                ... 
                total += somevalue;
                }
            } while (employeeDataProvider.cursorNext());
        } catch (Exception ex) {
            error("put your message here" +
                    ex.getMessage());
            log("put your message here: " +
                    ex.getMessage(), ex);
        }
        return total;

Sometimes, you might have some columns that are bound to the underlying data provider and some that are not. So, how do you iterate through the columns that are not bound to the data provider's fields. For those columns, you can create a hash map in the session bean that is keyed on the row id. Then you can create a getter and setter like the following and bind the column to the property (nbrServings in this example).

    public Integer getNbrServings() {
        TableRowDataProvider rowData = 
           (TableRowDataProvider) getBean("currentRow");
        if (rowData == null) {
            return new Integer(1);
        } else {
            String rowId = rowData.getTableRow().getRowId();
            Integer nbrServingsValue = 
              (Integer) this.getNbrServingsMap().get(rowId);
            if (nbrServingsValue == null) {
                return new Integer(1);
            } else {
                return  nbrServingsValue;
            }
        }
    }
    
    public void setNbrServings(Integer nbrServings) {
        TableRowDataProvider rowData = 
            (TableRowDataProvider) getBean("currentRow");
        if (rowData != null) {
            String rowId = rowData.getTableRow().getRowId();
            this.getNbrServingsMap().put(rowId, nbrServings);
        }
    }

Then add something like the following to the session bean's init method.

        nbrServingsMap = new HashMap();

You can then iterate through the has map's set of values.

Friday Mar 03, 2006

Radio Buttons in Tables

Here is a quick hack for detecting what radio button was clicked in a Table component.

Use the Table Layout dialog to add a column to the table and set its Compnent Type be Radio Button.

Add this to the page bean:

    public String getCurrentRow() {
        return tableRowGroup1.getRowKey().getRowId();
    }
   
    public void setCurrentRow(int row) {
    }
   
    private Object lastSelected="0";
   
    public Object getRBSelected() {
        String sv = (String)radioButton1.getSelectedValue();
        return sv.equals(lastSelected) ? sv : null;
    }
   
    public void setRBSelected(Object selected){
        if (selected != null) {
            lastSelected = selected;
        }
    }

In either the Outline window or the Visual Designer, select radioButton1.

In the Properties window for radioButton1, set the name property (in the Advanced section) to buttonGroup.

In the Data section for radioButton1, click the ... button for the selected property. A dialog box appears.

Select Use Binding, Click the Bind to an Object tab, select RBSelected, and click OK.

The application will now use the getRBSelected() and setRBSelected() methods to display and save user input for this component.

In the Advanced section of the Properties sheet, click the ... button for the selectedValue property.

Select Use Binding, Click the Bind to an Object tab, select currentRow, and click OK.

The application will now use the getCurrentRow() method to return the selected value for this component.

Now to find out what as been selected. In this example, the code is in a button action method:

        String aRowId = (String)RadioButton.getSelected(
                "buttonGroup");
        RowKey aRowKey = stateDataProvider.getRowKey(aRowId);
        selectedStateStaticText.setText("You Selected " +
                stateDataProvider.getValue("STATE.STATENAME",aRowKey));

If you want the selection to remain for when the user returns to the page, then you can stick the properties in a session bean. But, then you need to consider what to do if the selected row doesn't exist anymore.

About

divas

Search

Categories
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