Tuesday Aug 21, 2007
Tuesday Aug 21, 2007
Thursday Aug 16, 2007
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 = ? |
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 09, 2007

If you would like the components to remain centered on a page when the browser is resized, try this trick.
.ctrFirstColumn { |
Monday Jul 02, 2007

Friday Jun 22, 2007
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:
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();
}
|
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);
} |
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));
} |
Yossarian, a Creator/NetBeans IDE user, submitted this tutorial to the Creator Community Docs Site: Simple Page Fragment Menu Example.
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);
} |
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.
Thursday Jun 14, 2007
We have been blogging about jMaki for over a year, and, during that time, the technology has gone through many iterations, making most of our posts obsolete. With the release of 9.3, there became enough changes that it was time to start reposting these mini tutorials. So, to start, here are new instructions for adding jMaki to a Visual Web Application project or a Sun Java Studio Creator project.
Note: To learn about the modifications, see Carla Mott's Big changes in jMaki blog entry.
Aug 6, 2007 Update: With the later versions, such as 9.6.1, they abstracted some of the functionalities into a separate JSF Compounds library ( jsfcompounds-0.0.2.jar), which you can download from https://ajax.dev.java.net/servlets/ProjectDocumentList?folderID=7871. You must add this jar file to your classpath, by right-clicking the Libraries node in the Projects window, choosing Add Jar/Folder, navigating to and selecting jsfcompounds-0.0.2.jar, and clicking Open. A symptom of this missing jar file is getting the following error in the JSP editor: java.lang.NoClassDefFoundError: com/truchsess/faces/compound/webapp/CompoundChildTagBase
/widgets for the desired
widget libraries. In this mini tutorial, you will use the Tree widget from
the Yahoo widget library, so, at a minimum, unzip the jmaki-yahoo
zip so that you end up with jmaki-dir/widgets/resources/yahoo./scripts/glue.js to project-dir/web.
/scripts/system-glue.js and jmaki-dir/scripts/jmaki.js
to project-dir/web/resources. /core/web/resources/config.json to
project-dir/web/resources. /lib/ajax-wrapper-comp.jar,
and click OK. /widgets/resources.
For this mini tutorial, you need to copy jmaki-dir/widgets/resources/yahoo
to project-dir/web/resources.xmlns:a="http://jmaki/v1.0/jsf" to the <jsp:root>
tag. Now you are done setting up your project resources and you can add the Tree
widget to your web page. One problem that you have to work around is that the
jMaki widgets do not expose their features using the Design-Time
API. What this means is that you will not be able to see the widgets in
the Visual Designer. In addtion, with jMaki, you wrap the component in an <a:widget>
tag. Even if you were to use a component from the Pallette, if you wrap the
component in an <a:widget> tag, the Visual Designer won't
see it. To make it easier to work with the widgets in the Visual Designer, I
usually put them inside layout components, such as the Grid Panel. That way,
I can position the widgets and be able to see in the Visual Designer where the
jMaki widgets are on the page.
Note: Work is in progress to provide the jMaki widgets in component libraries that will work in the Visual Designer. We did a JavaOne Hands-On Lab that covered how this is done.
border property
to 1 to make it easier to visualize the location of the widget
on the page. You can clear the border property when you are ready
to deploy.
<h:panelGrid binding="#{Page1.gridPanel1}" border="1" id="gridPanel1"
style="position: absolute; left: 48px; top: 48px">
<a:widget name="yahoo.tree"
value="{'root' : {
'title' : 'Food',
'expanded' : true,
'children' : [
{'title' : 'Nuts'},
{'title' : 'Fruit',
'children' : [
{'title' : 'Banana'}
]
}
]
}
}"/>
</h:panelGrid> |
<ui:script binding="#{Page1.script1}" id="script1">
var handler = function(message) {
alert('You selected ' + message.value.label);
}
jmaki.subscribe("/yahoo/tree/onClick", handler);
</ui:script> |
<webuijsf:script binding="#{Page1.script1}" id="script1">
var handler = function(message) {
alert('You selected ' + message.value.label);
}
jmaki.subscribe("/yahoo/tree/onClick", handler);
</webuijsf:script> |
Wednesday Apr 04, 2007
A customer recently sent email that he was having trouble migrating the Movie Administration Sample Application, originally written for Sun Java Studio Creator, into NetBeans Visual Web Pack. When he opened the project in VWP, he resolved the missing server error by setting the target server to the Bundled Tomcat server. Upon running the application, he received the following error message:
package javax.faces does not exist
This error indicates that the J2EE packages are not available to the Tomcat web server. The fix is to add the JSF 1.1 library to the project as follows:
A second problem, an HTTP 500 Status error, occurred when deploying the application. The server log included this error:
java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConfigThis is because the
standard.jar/jstl.jar are needed for deploying to the Tomcat server. Here's the fix:
For more information on migrating projects, see Importing a Sun Java Studio Creator 2 Project in NetBeans Visual Web Pack 5.5.
Wednesday Feb 07, 2007
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.
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);
}
}
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);
}
}
}
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();
}
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();
}
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);
}
}
Tuesday Jan 30, 2007
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:
<listener>
<listener-class>
org.apache.myfaces.webapp.StartupServletContextListener
</listener-class>
</listener>
Monday Jan 08, 2007
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.
Thursday Dec 21, 2006
Sometimes, when testing your Visual Web application, you might get a page with the following unhelpful error:
HTTP Status 500 -
type Status report
message
description The server encountered an internal error () that prevented it
from fulfilling this request.
To find out what the real problem, go back to the NetBeans IDE and click the tab for the server's log (usually in the same area as the output window). There, you will find a more helpful description of the error. For example, you might see:
Dec 21, 2006 5:24:21 PM org.apache.catalina.core.ApplicationDispatcher invoke SEVERE: Servlet.service() for servlet jsp threw exception javax.faces.el.PropertyNotFoundException: java.lang.RuntimeException: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'org.apache.derby.jdbc.ClientDriver'In this particular case, I had not made the database driver available to the server. I resolved the problem by copying my database's JDBC3 compliant driver to the server's common library folder. With the Tomcat server, this would be something like
apache-tomcat-5.5.17\common\lib.
If the error is a programming error, such as a class cast error, you can search through the error output for the name of your page. If such line exists in the output, it will show the line number of the erroneous statement. Look for the names of your managed beans as well.
You can send diagnostic statements to the log from your page beans and managed beans by calling log("put your message here").
Tuesday Dec 19, 2006
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.
Sunday Dec 17, 2006
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.
/*
* 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;
}
}
/**
* 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;
}
weekNumber startDate endDate
public String button1_action() {
getSessionBean1().setReportStartDate(
(Calendar)getValue("#{currentRow.value['startDate']}"));
getSessionBean1().setReportEndDate(
(Calendar)getValue("#{currentRow.value['endDate']}"));
return null;
}
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.
jsf netbeans creator dataprovider
Thursday Sep 21, 2006
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.
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;
}
|