Showing posts with label netbeans. Show all posts
Showing posts with label netbeans. Show all posts

Tuesday, January 15, 2008

Programmatically adding a jenia4faces Popup component to a Netbeans 6.0 VWP project

This post describes how you can programmatically add a jenia4faces PopupFrame component to a Netbeans 6.0 Visual Web project.

There are various reasons why you would need to do that. In my case the requirement was that we needed a link in each row of a dynamically-created table that brings up a popup frame that is used for editing the database entry for this table row. Since the table is created dynamically, the same must be done with the PopupFrame component.

First you need to add the Jenia servlet in your web.xml file. This is a required step for using any Jenia component, no matter whether you add it to your page through JSP or from within Java code.

<servlet>
   <servlet-name>Jenia servlet</servlet-name>
   <servlet-class>org.jenia.faces.util.Servlet</servlet-class>
   <load-on-startup>
   </load-on-startup>
</servlet>
<servlet-mapping>
   <servlet-name>Jenia servlet</servlet-name>
   <url-pattern>/jenia4faces/*</url-pattern>
</servlet-mapping>
You also need the component jars in your project classpath.

Next you need to import the appropriate Java class in your Page bean. In the case of the PopupFrame this is

import org.jenia.faces.popup.component.html.HtmlPopupFrame;
If you want to dynamically add a different Jenia component, you can easily find the fully qualified name of the appropriate class by either browsing the Jenia jar files, or simply by using the Netbeans auto-completion function.

Now you can initialize the component and set its basic properties.

// Create the popup component
  HtmlPopupFrame popup = new HtmlPopupFrame();
// Set its properties
  popup.setId("editPopup");
  popup.setCenter("true");
  popup.setWidth("550px");
  popup.setHeight("400px");
  popup.setTitle("Edit Task");
  popup.setResizable("false");
  popup.setImmediate(true);
Again, you can use the auto-completion function in order to browse the supported properties and set any of those as required for your project.

Now it's the most tricky part: setting the method bindings for the actionOpen and actionClose properties. First we get a reference to the EL Expression Factory and create a MethodExpression.

  FacesContext fc = FacesContext.getCurrentInstance();
  ELContext elctx = fc.getELContext();
  ExpressionFactory elFactory = fc.getApplication().getExpressionFactory();
  MethodExpression openExpression = elFactory.createMethodExpression(elctx,
          "#{Staff.fireEditPopup}", String.class, new Class[]{});
Then we create a method binding using this expression and bind the actionOpen property.
   MethodBindingMethodExpressionAdapter bind1 = new MethodBindingMethodExpressionAdapter(openExpression);
   popup.setActionOpen(bind1);
Repeat the steps above for the actionClose attribute.

The PopupFrame component renders as a <a>. It can accept either plain text or an image as a child, so that it displays as a simple (text) hyperlink or an image hyperlink. This leaves us with an option to use either a StaticText or am ImageComponent in Netbeans. If you are not using Netbeans, you can add the respective standard JSF components (eg. <h:outputText>).

 // Create an image component
   ImageComponent edit = new ImageComponent();
   edit.setId("editLink");
   edit.setUrl("resources/edit.png");
   edit.setHeight(16);
   edit.setWidth(16);

   // Add the image to the popup (as a child)
   popup.getChildren().add(edit);

The Popup component is now ready. We can add it to the component tree. (In my case, I am adding it to the tablecolumn.)

column8.getChildren().add(popup);

Thursday, November 29, 2007

Displaying a spinning wheel image during a Dynamic Faces Ajax transaction.

I am currently building a JSF application using Netbeans 6.0. For this project I use a wide range of Woodstock components and also the Dynamic Faces extension to ajaxify some of these . As some Ajax transactions may take some time to complete, I wanted to provide the user with some visual feedback that something is happening in the background.

So these are the steps you need to follow in order to display a spinning wheel gif while the client is waiting for the server response.

  • Visit the Ajax loading gif generator and create a gif. There are plenty of similar sites in the web.
  • And an image component to the web page. This must be initially hidden, so specify visibility: hidden in the style attribute of the image. I suggest this property over the display: [none/block], because the visibility property reserves the space occupied by a hidden component.
  • Create a Javascript function that toggles the image visibility and makes it visible.
    var showLoading=function(element) {
        var loadingImage = $(element);
        loadingImage.style.visibility = 'visible';
    }
    
    This function receives one string argument (the id of the image) and uses the prototype dollar function.
  • Now we need to call this method when the ajax transaction is initiated. This happens in the onClick event action method of a button or hyperlink component, by calling the DynaFaces.Tx.fire(...) function. So we just need to add a call to the showLoading function right before this.
  • The final step is to hide the image when the transaction completes. This can be done by adding the image component to the "re-render" list of components of the AjaxTransaction component. This is enough, because when the image component is re-rendered when the response is received, it uses the initial value of the visibility property, which is set to 'hidden'.

Thursday, November 15, 2007

Internationalizing Woodstock components

Project Woodstock offers a set of very useful JSF components, some of which are included by default in NetBeans 6.0. The labels, messages etc used by these components can be internationalized by following these steps:

  1. Create a new resource bundle properties file woodstock.properties. An existing one can be used, but it's better to keep things clean.
  2. Declare the bundle in web.xml.
    <context-param>
            <param-name>com.sun.webui.theme.THEME_RESOURCES</param-name>
            <param-value>my.package.woodstock</param-value>
    </context-param>
    Note that you must use the fully qualified name of the properties file (if it is placed in a package).
  3. The Woodstock Theme Doc pages include a list with all the key-value pairs for woodstock messages. You can override these in the new properties file.

Tuesday, November 13, 2007

Dynamic Faces and encoding problems

Dynamic Faces is part of the JSF extensions project, and it offers an easy way to ajaxify plain old JSF components. However, there is a problem (I would call it a bug) with international characters. Even if you specify UTF-8 as the encoding of the HTML/JSP page, the partial AJAX response is always in ISO-8859-1. This can be easily verified with the Netbeans HTTP monitor: under the Session tab, the value for the javax.faces.request.charset is UTF-8 before the request, and changes to ISO-8859-1, after the request. This results in lots of questionmarks or strange symbols in the page and it actually makes it impossible to use Dynamic Faces with an internationalized application.

The solution came from Matthias Unverzagt's comment in a number of blogs/forums, such as Hong's blog. Matthias suggests that the line

context.getExternalContext().setResponseCharacterEncoding("UTF-8");

needs to be added to the com.sun.faces.extensions.avatar.lifecycle.AsyncResponse's installOnOffResponse method.

This proved quite of a challenge for me, since it required recompilation of the jsf-extensions-dynamic-faces-0.1.jar, which was a bit tricky, as this jar appeared in a number of locations on my system:

  • ~/.netbeans/6.0beta2/config/org-netbeans-modules-visualweb-complib/installed-complibs/dynamicfaces02
  • ${netbeans_installation_dir}/visualweb1/modules/ext
The jars in these directories were different. The first directory also contained a jar with the sources, but NetBeans was using the jar from the second directory for my project.

So, here are the steps I followed (with NetBeans Beta2):

  1. I extracted jsf-extensions-dynamic-faces-0.1-sources.jar, found in the first directory above.
  2. I created a new Netbeans Java project with the extracted sources.
  3. In order to compile this project a number of libraries and jars had to be added to the project's classpath:
    • libraries: JSF 1.2, Web UI Components
    • jars el-api.jar, jsp-api.jar, servlet-api.jar, shale-remoting.jar
    The first 3 jars can be found in tomcat's lib directory, while the last one is located in ~/.netbeans/6.0beta2/config/org-netbeans-modules-visualweb-complib/installed-complibs/dynamicfaces02
  4. I opened the file AsyncResponse.java file, from the com.sun.faces.extensions.avatar.lifecycle package and added the line
    context.getExternalContext().setResponseCharacterEncoding("UTF-8");
    to the installOnOfResponse method's body. It probably doesn't matter where exactly you place this line; I added it as the second line of this method, right between the other two statements of this method.
  5. I extracted the jsf-extensions-dynamic-faces-0.1.jar file from the ${netbeans_installation_dir}/visualweb1/modules/ext directory and replaced the .class files in the lifecycle subdirectory with the ones I just compiled.
  6. That's all! I then recompiled and deployed my web application (so that the patched copy of jsf-extensions-dynamic-faces-0.1.jar would be used) and I was set.

Wednesday, October 31, 2007

Datasources, Tomcat and Netbeans

I am currently developing a JSF application using NetBeans 6.0 and Tomcat 6.0.14. When I tried to deploy the application on our production server (by just dumping the .war file in Tomcat's webapps directory, it didn't work properly. I could access the app's start page, but it failed to render the following pages.

A look in tomcat's log files revealed that there was a problem with the mysql driver.

Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

I tried to make sure that the mysql-connector jar is included in the project's imported libraries and that it can be found in META-INF/lib, but this didn't help. I later found out that in Netbeans, under Tools→Servers→Deployment there is a "Enable JDBC driver deployment option". Disabling this resulted in a replication of the problem on my development machine, even when using NetBeans. So I had to find out what it was that NetBeans was doing when this option was enabled and repeat it on the production server.

I started making a research on the net, based on the error message I was getting. The oslution proposed by most people was to place the mysql driver jar in tomcat's common/lib directory and nowhere else, but this just wouldn't do the trick for me. I also checked that the datasource's declarations in the web.xml and context.xml files were correct.

A final attempt to go through the steps to create and declare a datasource as described in tomcat's website revealed a small detail in step 1: the driver jar file needs to be placed in the $CATALINA_HOME/lib directory rather than $CATALINA_HOME/common/lib.

Still remains to check whether there is a difference in the directory structure in versions 5.5 and 6.0 of tomcat, since no common directory appears to exist in installations of tomcat 6.0.

Thursday, August 30, 2007

How to create a Datasource and a Connection Pool on Tomcat.

This post describes how you can setup a Connection Pool for a web application under Tomcat. I have been using NetBeans 5.5.1, with bundled Tomcat (version 5.5.17). NetBeans does offer some visual tools to create datasources and connection pools, but as far as I understand, these only work with the Sun Application Server.

Before doing anything else, the following jars are required:

  • mysql-connector-java-5.0.7-bin.jar
  • commons-dbcp-1.2.2.jar
  • commons-collections-3.2.jar
  • commons-pool-1.3.jar
The first one is the official mysql driver which can be downloaded from the mysql site. The other three are part of the Apache Commons collection.
They need to be placed in the WEB-INF/lib subdirectory of the webapp. (Of course this can also be done through the NetBeans IDE.) Actually, although I read on various websites about the last 3 jars, I am not absolutely sure if they are definitely required. Even after I removed them, my application continued to work fine.
Important: The MySQL Connector/J jar needs to be placed under the Tomcat common/lib/ subdirectory. (For the bundled with the NetBeans IDE version of Tomcat, this directory is $NETBEANS_HOME/enterprise3/apache-tomcat-5.5.17/common/lib.


1. Add this to the context.xml file (which is located in the META-INF directory of the web-app.

<Context path="/ePmashup">
  <Resource 
      name="jdbc/dataSource"
      auth="Container"
      type="javax.sql.DataSource"
      factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
      username="username"
      password="password"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/databaseName"
      maxWait="1000"
      removeAbandoned="true"
      maxActive="30"
      maxIdle="10"
      removeAbandonedTimeout="60"
      logAbandoned="true"/>    
</Context>
The options in italics have to be substituted with the appropriate values.

2. Create a DataSource object in the application code.

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
datasource = (DataSource)envContext.lookup("jdbc/dataSource");
This snippet has to be wrapped in a try-catch block, because it might throw a NamingEsception. In my code, I placed this piece of code in the init() method of the Servlet that contacts the database and returns the results to the client.
 public void init() throws ServletException {
   super.init();
   try {
       Context initContext = new InitialContext();
       Context envContext  = (Context)initContext.lookup("java:/comp/env");
       datasource = (DataSource)envContext.lookup("jdbc/dataSource");
          
   } catch( NamingException ne ) {
     throw new RuntimeException( "Unable to aquire data source", ne );
  }
 }
Obviously, the string passed in the lookup method, needs to be the Resource name (in context.xml).

3. Now, a connection from the pool can be retrieved and used like this:

Connection conn = dataSource.getConnection();