Tuesday Aug 21, 2007

Relatively Positioning Web UI Components

Tip on positioning Web UI components based on the width of the browser window in a NetBeans Visual Web Application or a Sun Java Studio Creator Application.[Read More]

Thursday Aug 16, 2007

SqlException: At least one parameter to the current statement is uninitialized

When you do the Using Databound Components to Access a Database tutorial, you learn how to use the Query Editor on the rowset to build the SQL statement to retrieve the desired set of data. You also learn that for every ? (parameter) in your query, you need to call setObject() on the rowset before the query is executed. Take, for example, the following query.

SELECT ALL TRAVEL.TRIP.TRIPID, 
           TRAVEL.TRIP.PERSONID, 
           TRAVEL.TRIP.DEPDATE 
FROM TRAVEL.TRIP
WHERE TRAVEL.TRIP.PERSONID = ?
   AND TRAVEL.TRIP.TRIPTYPEID = ? 
This query has two parameters, PERSONID and TRIPTYPEID. What this means is that you have to provide values for these two parameters before the rendering phase. You typically do this in the prerender() method, as shown in the following code example.
public void prerender() {
    if ( personIdDD.getSelected() == null ) {
        try {
          personDataProvider.cursorFirst();
          getSessionBean1().getTripRowSet().setObject(
            1, personDataProvider.getValue("PERSON.PERSONID"));
          getSessionBean1().getTripRowSet().setObject(
            2, "4");
          tripDataProvider.refresh();
        } catch (Exception e) {
          error("Cannot switch to person " +
              personDataProvider.getValue("PERSON.PERSONID"));
            log("Cannot switch to person " +
              personDataProvider.getValue("PERSON.PERSONID"), e);
        }
    }
}

If you forget to set the parameters before the rendering phase, you usually get the following error.

SqlException: At least one parameter to the current statement is uninitialized.

You will also get an error like this if you do not set all the parameters. Such as only calling setObject(1, somevalue) when you have two parameters in the query.

Another common error is to forget to edit the query to add the parameters. If you call setObject(1, somevalue), but your query has no parameters (no ?), you might get an error like the following.

java.lang.NullPointerException
at org.apache.derby.client.am.PreparedStatement.checkForValidParameterIndex(Unknown Source)

Similarly, if you call setObject(2, somevalue) when your query has only one parameter, the server will emit something like the following message.

SqlException: The parameter position '2' is out of range.  
The number of parameters for this prepared  statement is '1'

Monday Jul 02, 2007

Laying Out Multiple Table Components



You can use the layout components, such as the Group Panel and the Grid Panel, to easily layout and size container components, such as the Table component. In the screen shot above, the two tables on the left are in a Group Panel, and the two on the right are in a Grid Panel. I can resize or move either panel in the Visual Designer, and the contents will resize and move in accordance (they won't resize in the Visual Designer, but they will resize in the client). The trick is to set the width property of each tables to 100% so that they resize based on the size of their container.

Because the Visual Designer does not display the widths of the tables accurately, you have to right-click on the page and choose Preview in Browser to get a feel of how the tables will actually appear in the client.

Tips:

  • Set the Group Panel component's block property to true. This encloses the panel in a <div> tag.

  • You can set the Group Panel component's separator property to <br /><br /> to put spacing between the tables.

  • Set the Table component's width property to 100%. If you make changes to the table, the IDE may reset this property so keep checking to make sure it is 100%.

  • I find it best to leave the Table Column width properties blank or set them at percentage amounts, such as 10%.

Friday Jun 22, 2007

Page Fragment Tips

7/16/07 Update: Thanks to Antonio, this blog entry is now available in Spanish.

Page fragments enable you to add a particular set of components, action handlers, and functions to a bunch of web pages. When you add a Page Fragment Box to a page, you are first given the option of choosing an existing page fragment or creating a new one, and then the IDE adds a <jsp:directive.include> tag to the main page (the page that includes the fragment). When you create a page fragment, the IDE adds both a .jspf file and a backing bean to the project.

The <jsp:directive.include> directive is not the same as, the <jsp:include> standard action. The directive causes the contents of the page fragment to be placed into the main page's .jsp before the .jsp file is translated into a servlet.

The page fragment's backing bean extends AbstractFragmentBean, which, unfortunately, does not provide the preprocess or prerender methods. It only provides the init and destroy methods. When a person lands on the page from another destination, such as by typing in the URL or clicking a link, the server instantiates the fragment's backing bean (and thus calls the init method) the first time that fragment is referenced. In general, this is likely to happen during the render response phase. On a postback (that is, when the page redisplays itself in response to a page submission) , the fact that the saved component state includes component bindings to properties in the fragment's backing bean will cause the server to instantiate the page fragment's backing bean much earlier.

Because the page fragment's init method can be called early in the lifecycle, you cannot reference or set component values in the init method. Conversely, a page fragment's init method might not be called until during or after the main page's prerender call. A workaround for this is to put methods in your page fragements and call those methods from the main page's prerender. For example, you can add a prerenderFragment method in each of your page fragments. Then for each fragment that you include in the main page, add code like the following:

public void prerender() {
      TopFragment topFragment = (TopFragment)getBean("TopFragment");
      topFragment.fragmentPrerender();
      ...
  }

Here are some code snippets to illustrate some common page fragment tasks:

Passing Data Between the Main Page and the Page Fragment

You can pass data to a page fragment through the a managed bean (request bean, session bean, application bean), or through function arguments as shown below

In the following snippit, the main page passes information to the page fragment by argument:

  public void prerender() {    
     Bike bike = getSessionBean1().getBike();
    ...
    PriceTable priceTable = (PriceTable) getBean("PriceTableFragment");
    totalsSubtotalPrice.setText(priceTable.subtotal(bike));
  }

Here, the main page sets the values in the request bean, which the page fragment then picks up and uses. This is from a web application where the user selects an item from a drop-down list in the main page, which, in turn, refreshes the trip data provider in the page fragment.

    // Page Fragment
    public void fragmentPrerender() {
        if (getRequestBean1().getPersonId() != null) {
            try {
                getSessionBean1().getTripRowSet().setObject(
                        1, getRequestBean1().getPersonId());
                tripDataProvider.refresh();
            } catch (Exception e) {
                error("Cannot switch to person " +
                        getRequestBean1().getPersonId().toString());
                log("Cannot switch to person " +
                        getRequestBean1().getPersonId().toString(), e);
            }
        }
    }
    // Main Page
    public void prerender() {
        // If not a postback, set the default person
        if (getRequestBean1().getPersonId() == null) {
            try {
                personDataProvider.cursorFirst();
                getRequestBean1().setPersonId(
                  (Integer)personDataProvider.getValue("PERSON.PERSONID"));
            } catch (Exception e) {
                error("Cannot switch to person " +
                        personDataProvider.getValue("PERSON.PERSONID"));
                log("Cannot switch to person " +
                        personDataProvider.getValue("PERSON.PERSONID"), e);
            }
        }
        Fragment1 fragment1 = (Fragment1) getBean("Fragment1");
        fragment1.fragmentPrerender();
    }	

Changing Component Properties in a Page Fragment

The main page can access and modify components in the page fragment through the page fragment's bean object, as shown below:

  public void prerender() { 
    Navigation navigationFragmentBean = (    
    Navigation)getBean("Navigation");
    Hyperlink homeLink = navigationFragmentBean.getHomeLink();
    homeLink.setDisabled(true);
 }

Determining What Page the Page Fragment is Included In

In this code snippet, the page fragment changes its apperance based on what page it is being displayed in.

    public void fragmentPrerender() {
        // If they are done, show the checkout button
        String page;
        String viewId = getFacesContext().getViewRoot().getViewId();
        if (viewId == null || viewId.length() == 0 || "/".equals(viewId)) {
            page = "";
        } else {
            int pos = viewId.lastIndexOf('/');
            if (pos == viewId.length() - 1) { 
                // last char in viewId is '/'
                viewId = viewId.substring(0, pos);
                pos = viewId.lastIndexOf('/');
            }
            //ok if pos is -1, then pos+1 will be 0
            page = viewId.substring(pos+1);
        }
        checkoutButton.setRendered(FINAL_ORDER_PAGE.equals(page));
    }

Using a Tab Set in a Page Fragment for Navigation

Yossarian, a Creator/NetBeans IDE user, submitted this tutorial to the Creator Community Docs Site: Simple Page Fragment Menu Example.

Dynamically Rendering a Page Fragment Component From the Main Page

Here is a snippit where the main page dynamically renders a tree in a page fragment

    public void makeTree() {
        Fragment2 pgfrag = (Fragment2)getBean("Fragment2");
        List children = pgfrag.getDisplayTree().getChildren();
        TreeNode personNode = new TreeNode();
        personNode.setId("node1");
        personNode.setText("Shari Oln");
        children.add(personNode);
    }

Other Examples

In Winston's blog he points to Josh's web site, which uses VWP page fragments to do wonderous things. How about you? Do you have some super page fragment tips to share? If so, post them to the comments below to share with other VWP developers.

Wednesday Feb 07, 2007

Coordinated Drop-Down Lists

I have seen a lot of inquiries in the users alias and the forum about how to do coordinated drop-down lists. Coordinated drop-downs are basically a set of nested master-detail records that follow the same pattern that we show in Using Databound Components to Access a Database. With coordinated drop-downs, whenever the user selects a new item from the master drop-down, you need to refresh the list in the detail drop-down.

In the following example, I show how to coordinate drop-down lists that contain data from the Travel database. The first drop-down lists all the PERSON records. The second drop-down shows all the TRIP records for the selected PERSON, and the third drop-down shows all the FLIGHT records for the selected TRIP. Finally, the detail data shows data from the selected FLIGHT.

The trick with coordinating multiple drop-downs, is that you need to trickle down the refreshing of the lists. A change in the first drop-down's selection requires refreshing the second list, which in turn, requires refreshing the third list, and so on.

In this example, I took the easy route. When the user makes a new selection from the PERSON drop-down, I select the first record by default and coordinate the TRIP drop-down by showing all the trips for the first-person. Then, I show all the flights for the first TRIP record, and the detail data for the first FLIGHT record.

  1. Create your Sun Java Studio Creator (JSC) or NetBeans Visual Web Pack (VWP) project.

  2. Drop three Drop Down List components, a Property Sheet component, and a Message Group component onto the page in the Visual Designer. The Message Group component is to help diagnose problems if something goes wrong.

  3. Select each component and, in the Properties window, change the id property as follows, from top to bottom:

    1. personDD
    2. tripDD
    3. flightDD


  4. Drag the PERSON table from the Travel database (in the Servers window for JSC, and in the Runtime window for VWP), and drop it on the personDD Drop Down List component in the Visual Designer.

  5. Drop the TRIP table on the tripDD component, and drop the FLIGHT table on the flightDD component.

  6. Right-click each Drop Down List component and choose Bind to Data. Make the following selections:

    1. personDD. Value Field: PERSON.PERSONID, Display Field: PERSON.NAME
    2. tripDD. Value Field: TRIP.TRIPID, Display Field: TRIP.DESTCITY
    3. flightDD. Value Field: FLIGHT.FLIGHTID, Display Field: FLIGHT.DEPAIRPORT


  7. Now, right-click each Drop Down List component and choose Auto-Submit on Change from the pop-up menu. This will cause the page to be submitted to the server each time a new selection is made from any list, and will cause the appropriate change event handlers to be called.

  8. Drag the FLIGHT table again, but this time drop it on a blank spot on the page. A dialog box appears. Choose the radio button for creating a flightRowSet in the page bean, and click OK.

    I chose to put the other queries in the session bean because I didn't want to lose the query data everytime the page is submitted. As the detail data pretty much changes on each submission, I am choosing to put this rowset in the page bean.

  9. In the Outline window, double-click the SessionBean1 > tripRowSet node to open it in the Query Editor. In the Query Editor, right-click on the PERSONID cell in the first column and choose Add Query Criteria. Select the Parameter radio button, click OK and close the Query Editor.

  10. Do the same for the flightRowSet, but add the query criteria for the TRIPID. Close the Query Editor.

  11. Now, double-click the flightRowSet in the page bean, add query criteria for FLIGHTID, and close the Query Editor.

    This query is for the detail data.

  12. Display the page in the Visual Designer (it should be displayed already), and click Java to switch to the source editor.

  13. Add the following code to the bottom, just before the final end brace:
    public void initFlightDropDown() {
        try {
            tripDataProvider.cursorFirst();
            getSessionBean1().getFlightRowSet().setObject(
                    1, tripDataProvider.getValue("TRIP.TRIPID"));
            flightDataProvider.refresh();
        } catch (Exception e) {
            error("Cannot switch to trip " +
                    tripDataProvider.getValue("TRIP.TRIPID"));
            log("Cannot switch to person " +
                    tripDataProvider.getValue("TRIP.TRIPID"), e);
        }
    }
    
    public void initFlightDetail() {
        try {
            flightDataProvider.cursorFirst();
            flightRowSet.setObject(
                    1, flightDataProvider.getValue("FLIGHT.FLIGHTID"));
            flightDataProvider.refresh();
        } catch (Exception e) {
            error("Cannot switch to flight " +
                    flightDataProvider.getValue("FLIGHT.FLIGHTID"));
            log("Cannot switch to flight " +
                    flightDataProvider.getValue("FLIGHT.FLIGHTID"), e);
        }
    }
    
  14. Add the following code shown in bold to the prerender method:
    public void prerender() {
        if ( personDD.getSelected() == null ) {
            try {
                personDataProvider.cursorFirst();
                getSessionBean1().getTripRowSet().setObject(
                        1, personDataProvider.getValue("PERSON.PERSONID"));
                tripDataProvider.refresh();
            } catch (Exception e) {
                error("Cannot switch to person " +
                        personDataProvider.getValue("PERSON.PERSONID"));
                log("Cannot switch to person " +
                        personDataProvider.getValue("PERSON.PERSONID"), e);
            }
            initFlightDropDown();
            initFlightDetail();
        } else {
            try {
                // Synchronize data providers with current selections
                personDataProvider.setCursorRow(
                        personDataProvider.findFirst(
                        "PERSON.PERSONID", personDD.getSelected()));
                tripDataProvider.setCursorRow(
                        tripDataProvider.findFirst(
                        "TRIP.TRIPID", tripDD.getSelected()));
                flightDataProvider.setCursorRow(
                        flightDataProvider.findFirst(
                        "FLIGHT.FLIGHTID", flightDD.getSelected()));
    
            } catch (Exception e) {
                error("Cannot switch to selections");
                log("Cannot switch to selections", e);
            }
        }
    }
    
  15. Click Design in the editing toolbar to switch to the In the Visual Designer.

  16. Double-click the personDD Drop Down component (the top one) to cause the IDE to add a process value change handler for the component. The IDE switches to the added code. Add the following code shown in bold to the method:
    public void personDD_processValueChange(ValueChangeEvent event) {
        try {
            getSessionBean1().getTripRowSet().setObject(
                    1, personDD.getSelected());
            tripDataProvider.refresh();
        } catch (Exception e) {
            error("Cannot switch to person " +
                    personDataProvider.getValue(
                    "PERSON.PERSONID"));
            log("Cannot switch to person " +
                    personDataProvider.getValue(
                    "PERSON.PERSONID"), e);
        }
        initFlightDropDown();
        initFlightDetail();
    }
    
  17. Click Design to switch back to the Visual Designer, double-click the tripDD Drop Down List component (the middle one) to create its change event handler, and add Add the following code shown in bold to the method:
        public void tripDD_processValueChange(ValueChangeEvent event) {
            try {
                getSessionBean1().getFlightRowSet().setObject(
                        1, tripDD.getSelected());
                flightDataProvider.refresh();
            } catch (Exception e) {
                error("Cannot switch to trip " +
                        tripDataProvider.getValue(
                        "TRIP.TRIPID"));
                log("Cannot switch to trip " +
                        tripDataProvider.getValue(
                        "TRIP.TRIPID"), e);
            }
            initFlightDetail();        
        }
    
  18. Click Design one more time and double-click the flightDD Drop Down List component (the bottom one). Add the following code shown in bold the change event handler:
    public void flightDD_processValueChange(ValueChangeEvent event) {
        try {
            flightRowSet.setObject(
                    1, flightDD.getSelected());
            flightDataProvider1.refresh();
        } catch (Exception e) {
            error("Cannot switch to flight " +
                    flightDataProvider.getValue(
                    "FLIGHT.FLIGHTID"));
            log("Cannot switch to flight " +
                    flightDataProvider.getValue(
                    "FLIGHT.FLIGHTID"), e);
        } 
    }
    
  19. Take a look at the code you have added. The code in the prerender method first handles the case where the user first lands on the page and nothing has been selected. It seeds the drop-down lists with the first record from the PERSON query and synchronizes queries for the nested detail drop-down lists and the detail data. If there is a selected person, it synchronizes the cursor positions in the queries with the drop-down list selections.

    The change event handlers synchronize the appropriate detail queries. A change in PERSON selection refreshes the trip, flights, and flight detial queries. A change in TRIP selection refreshes the flights and flight detail queries, and a change in FLIGHT selection refreshes the flight detail query.

  20. The last thing we need to do is to display some detail information. Click Design to display the page and, in the Outline window, expand propertySheet1, expand section1, and select property1 (you can also select the property1 in the Visual Designer, but I find it easier to work with the property sheet in the Outline window).

  21. In the Properties window, change the label property to Airline:.

  22. Drop a Static Text component on property1 in the Outline window.

  23. Expand property1, right-click staticText1, and choose Bind to Data.

  24. Choose flightDataProvider1 (not flightDataProvider) from the drop-down list, select FLIGHT.AIRLINENAME, and click OK.

  25. If you want, you can add more Property components to the Property Sheet Section, add Static Text components to the Property components, and bind the Static Text components to other columns in the database table, as I did in the above screenshot.

  26. Now you are ready to click Run Main Project and test your coordinated drop-downs.

Tuesday Jan 30, 2007

Missing Image Bug

I just finished writing a NetBeans Visual Web Pack version of the JasperReports tutorial Generating Reports and PDFs From a Web Application. The NetBeans version should appear on the portal sometime today.

While working on this tutorial, I came across a bug that prevented the company logo from appearing in the HTML output when the application is deployed to version 9 of the Sun Java System Application Server. The bug happens when you request binary data through the FacesServlet, and the fix is in for version 9.1. Ryan and Craig were the engineers who figured out why the problem was happening. They both pointed out to me that the following statement in my code sample, which sets a relative url, is not recommended:

  exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image?image="); 

The above statement results in following HTML:

  http://localhost:8080/TravelReport/faces/image?image=img_0_0_0

By using the relative URL, I was needlessly incurring, for a non-JavaServer Faces entity, the extra overhead that is associated with a JavaServer Faces request. It is better to serve up the image directly, instead of going through the JavaServer Faces lifecycle.

I am pushing out a new version of the Java Studio Creator tutorial today, which shows the correct way to pass the url (which happens to work with Sun Java Application Server 9):

   exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,
     request.getContextPath() + "/image?image="); 

While we are talking about server bugs, a customer wrote to me that they were getting a java.lang.NullPointerException from the javax.faces.component.UIComponentBase class's getRenderer method whenever they use the Table component in web applications deployed to JBoss. This is a known bug, and is documented in the Release Notes. What is happening is that when you create a Visual Web project, the classpath on the container is checked. If the IDE finds a MyFaces implementation, it gives the MyFaces implementation precedence over the JavaServer Faces Reference Implementation libraries. To prevent this problem from happening, delete or move the JBOSS_HOME/server/default/deploy/jbossweb-tomcat55.sar/jsf-lib directory before you create the Visual Web Pack project for that container. This forces the the IDE to bundle the JSF Reference Implementation with the project.

To go back to using the MyFaces run time for running non-Visual Web Pack based applications, follow these steps:

  1. In the Projects window, right-click the Libraries node and choose Add Library.
  2. In the Add Library dialog box, select the desired MyFaces binaries.
  3. Click Add Library.
  4. Make sure the JSF-RI libraries are not deployed.
  5. Modify web.xml to include the following:
  6. <listener>
      <listener-class>
        org.apache.myfaces.webapp.StartupServletContextListener
      </listener-class>
    </listener>
    

Tuesday Dec 19, 2006

Workaround for Button Component Viewed in IE7

When a web page that includes the Web UI Button component is viewed by the Internet Explorer 7 browser, the button component might be rendered with an incorrect width. This problem occurs when the Button component is placed on the page using absolute positioning.

You can use either of the following workarounds to solve this problem.

  • Specify the width property for the button, or resize the button in the Visual Designer to make the IDE assign a width to the button.
  • In the Visual Designer, nest the Button component inside a Group Panel component. By doing this, you move the absolute positioning from the button to the panel, outside the button.

Sunday Dec 17, 2006

Using the Object Array Data Provider

A forum poster recently asked for the following information:

I have a table with 5 columns, (week_no, objective, date1, date2 and add report). How do I get the date for date1( example, today's date)? How do I set the week number as auto increment by 1( example, row 1, the week_no is 1, row 2, the week_no is 2 and so on)? Lastly, how to I set the add report button to link to another JavaServer Pages file?

This scenario gives me an excellent opportunity to show how to use an Object Array Data Provider (OADP). I usually use the Object List Data Provider (OLDP), but OLDPs take a bit more work. (See the Using Hibernate tutorial for an OLDP example.) If you have a simple array of data, the OADP might be the better choice, as in this case. The following steps create a table similar to the one requested in the forum.

  1. Create a web application named ArrayTableExample.

    (If using the Visual Web Pack, be sure to create a Visual Web Application.)

  2. Create a JavaBeans object for the array. In this example, I chose to put the week number, start date, and end date in the bean. In the Projects window, right-click Source Packages > arraytableexample, choose New > Java Class, name the class WeekBean, and click Finish.
  3. Replace the class definition with the following code shown in bold.
    /\*
     \* WeekBean.java
     \*
     \*/
    
    package arraytableexample;
    
    public class WeekBean 
            extends Object implements Serializable {
        
        private int weekNumber;
        private Calendar startDate;
        private Calendar endDate;
        private int dayOfWeek; 
        
        public WeekBean(int weekNumber) {
            this.weekNumber = weekNumber;        
            Calendar workingDate = Calendar.getInstance();
            workingDate.set(java.util.Calendar.HOUR_OF_DAY, 0);
            int offset = weekNumber - 1; 
            workingDate.add(
                Calendar.DAY_OF_YEAR, 
                + (offset \* 7));
            dayOfWeek = workingDate.get(Calendar.DAY_OF_WEEK);
            startDate = (Calendar) workingDate.clone();   
            startDate.add(
            Calendar.DAY_OF_YEAR, - (dayOfWeek - Calendar.SUNDAY));
            endDate = (Calendar) workingDate.clone();
            endDate.add(
                Calendar.DAY_OF_YEAR,
                + (Calendar.SATURDAY - dayOfWeek));
        }
        
        public WeekBean() {
            this(1);
        }
            
        public int getWeekNumber() {
            return this.weekNumber;
        }
        
        public void setWeekNumber(int weekNumber) {
            this.weekNumber = weekNumber;
        }
        
        public Calendar getStartDate() {
            return this.startDate;
        }
        
        public void setStartDate(Calendar startDate) {
            this.startDate = startDate;
        }
        
        public Calendar getEndDate() {
            return endDate;
        }
        
        public void setEndDate(Calendar endDate) {
            this.endDate = endDate;
        }
    }
    
  4. Right-click in the code and choose Fix Imports. Make sure the Fully Qualified Name for Calendar is java.util.Calendar, and click OK.

  5. Close and save the file.

  6. In this example, we want the table to show the same data throughout the session, so put the array property in the session bean. In the Projects window, double-click the Session Bean node to open SessionBean1.java in the source editor.

  7. Add the following code to the bottom of the class defintion, just before the ending brace. This code also adds properties for passing the selected start and end dates to other pages.
    
        /\*\*
         \* Holds value of property weeks.
         \*/
            WeekBean[] weeks = {
                new WeekBean(1),
                new WeekBean(2),
                new WeekBean(3),
                new WeekBean(4)
            };
    
        /\*\*
         \* Getter for property weeks.
         \* @return Value of property weeks.
         \*/
        public WeekBean[] getWeeks() {
            return this.weeks;
        }
        
        /\*\*
         \* Holds value of property reportStartDate.
         \*/
        private Calendar reportStartDate;
    
        /\*\*
         \* Getter for property reportStartDate.
         \* @return Value of property reportStartDate.
         \*/
        public Calendar getReportStartDate() {
    
            return this.reportStartDate;
        }
    
        /\*\*
         \* Setter for property reportStartDate.
         \* @param reportStartDate New value of property reportStartDate.
         \*/
        public void setReportStartDate(Calendar reportStartDate) {
    
            this.reportStartDate = reportStartDate;
        }
    
        /\*\*
         \* Holds value of property reportEndDate.
         \*/
        private Calendar reportEndDate;
    
        /\*\*
         \* Getter for property reportEndDate.
         \* @return Value of property reportEndDate.
         \*/
        public Calendar getReportEndDate() {
    
            return this.reportEndDate;
        }
    
        /\*\*
         \* Setter for property reportEndDate.
         \* @param reportEndDate New value of property reportEndDate.
         \*/
        public void setReportEndDate(Calendar reportEndDate) {
    
            this.reportEndDate = reportEndDate;
        }
    
  8. Right-click in the code and choose Fix Imports. Make sure the Fully Qualified Name for Calendar is java.util.Calendar, and click OK.

  9. Close and save SessionBean1.java.

  10. View Page1 in the Visual Designer.

  11. In the Palette, expand the Data Providers section.

  12. Drag the Object Array Data Provider node and drop it on Page1.

  13. If the properties for the OADP do not appear in the Properties window, select Page1 > objectArrayDataProvider1 in the Outline window to make its properties appear.

  14. In the Properties window, change the id to weekDataProvider.

  15. Here is where it starts getting kludgy. You should be able to choose weeks from the array drop-down list, but it propably is not appearing at this point. If weeks is not in the drop-down list, choose Clean and Build Main Project from the main menu. After the build completes, close and reopen the project.

  16. In the Outline window, select Page1 > weekDataProvider.

  17. In the Properties window, select weeks (SessionBean1) from the array drop-down list.

  18. Drag a Table component from the Palette and drop it on Page1.

  19. Right-click the Table component and choose Table Layout.

  20. In the Table Layout dialog box, choose weekDataProvider from the Get Table From drop-down list.

  21. Use the Up and Down buttons to put the values in the Selected list in the following order:
    weekNumber
    startDate
    endDate
    
  22. (Optional) Set the Header Text values for the columns to Week, Start Date, and End Date.

  23. Click New to add another column.

  24. In the new column, set the Header Text to blank, select Button from the Component Type drop-down list, and set the Value Expression to Show Me.

  25. Click OK to dismiss the dialog box.

    Again, it gets kludgy. Only one row appears, which says "No items found", and there is no button. Don't worry, it will work out in the end.

  26. In the Outline window, expand table1 > tableRowGroup1 > tableColumn4, right-click button1, and choose Edit Action Event Handler.

    Page1.java opens in the source editor and scrolls to the newly added button1_action method.

  27. Add the code shown in bold to the method.
      public String button1_action() {
            getSessionBean1().setReportStartDate(
              (Calendar)getValue("#{currentRow.value['startDate']}"));
            getSessionBean1().setReportEndDate(
              (Calendar)getValue("#{currentRow.value['endDate']}"));        
            return null;
      }
    
  28. Right-click in the code and choose Fix Imports. Make sure the Fully Qualified Name for Calendar is java.util.Calendar, and click OK.

  29. Typically, you would set up page navigation to go to another page to display the report. For simplicity, click Design and drop a Static Text component on the page to display the selected start date.

  30. Right-click the Static Text component and choose Bind to Data.

  31. Click Bind to an Object, select SessionBean1 > reportStartDate, and click OK.

  32. Click Run Main Project. When the page appears, click the button in each row to verify that the action method returns the right value.

Winston has many blog entries about the dataprovider. A good place to start is his blog titled What is this Data Provider in Sun Java Studio Creator anyway?. Another good resource is Joel Brown's Weblog.

About

divas

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