NetBeans Visual Web Pack - Real World Apps Tip #2 - Dynamic Hyperlinks

In my last blog I covered creating Dynamic Content in NetBeans VWP (Visual Web Pack).  In this blog, I'll show you how to create "Hyperlink" components dynamically in VWP.

Creating the Hyperlink component and adding it is really not difficult.  But, hooking the Hyperlink component up to a Java backing beans is a different story.  This took me a while to figure out.

Creating the Hyperlink

Actually creating the "Hyperlink" component is easy.  Here's the code.

Hyperlink link = new Hyperlink();

Using the Hyperlink to Pass Data


As with most cases developing on the JavaServer Faces framework, you can't ignore the standard processing lifecycle.  Remember VWP uses a modified "Application Model" based off the one used by Java Studio Creator 2.  Why is this important?  In the case of a Hyperlink on a page, if you want something about the Hyperlink to be passed as data to the actual page bean method that will process the hyperlink click, you either need to use the SessionBean or the Hyperlink component itself.  The technique I'm about to show you uses the Hyperlink component.  Remember you can't use state on the page bean because a new instance of the page bean will be created on a postback.

To explain this, I'll use the example of the Plugin Portal when the categories are in list form rather than tag form.  Here's a snapshot of that area of the screen.

List

You can see that the Hyperlink has the category name and the number of items in that category.  In the Plugin Portal code, I needed the category name so I could show a category list of that category.  To pass that name to the method that would deal with the selection, I used the "Hyperlink.type" property.  The "type" property is used to set the MIME type of the hyperlink.  Since we are handling the link, we don't care about the MIME type so we can use this property to pass values.

So here is some code that creates the Hyperlinks using the type property.

        /\*\*
\* Now create the hyperlinks to add
\*/
Hyperlink dynamicHyperlink1 = new Hyperlink();
dynamicHyperlink1.setText("list1(" + list1.size() + ")");
dynamicHyperlink1.setType("list1");
Hyperlink dynamicHyperlink2 = new Hyperlink();
dynamicHyperlink2.setText("list2(" + list2.size() + ")");
dynamicHyperlink2.setType("list2");
Hyperlink dynamicHyperlink3 = new Hyperlink();
dynamicHyperlink3.setText("list3(" + list3.size() + ")");
dynamicHyperlink3.setType("list3");

/\*\*
\* Create a grid panel so we have one column.
\*/

HtmlPanelGrid listPanel = new HtmlPanelGrid();
listPanel.getChildren().add(dynamicHyperlink1);
listPanel.getChildren().add(dynamicHyperlink2);
listPanel.getChildren().add(dynamicHyperlink3);
/\*\*
\* Add the list grid panel to the layout panel.
\*/
dynamicPanel.getChildren().add(listPanel);

Mapping the Hyperlink to Backing Beans Methods

Now to the difficult part, at least before knowing what I'm about to show you. :)  Many times you want Hyperlinks to invoke some action on your Java backing bean.  To accomplish this, you'll need to know how to create a "MethodExpression".  A Hyperlink component has two properties for dealing with an action:

The ActionExpression is the method JavaServer Faces uses to determine page navigation.  The ActionListenerExpression will wrap the Hyperlink in the event and let us use the "Type" field as a way to pass data.  When a user clicks on the Hyperlink, the methods will be called in this order.

  1. ActionListener method
  2. Action method
To create a MethodExpression, you need the "ELContext".  You can get the "ELContext" from the "FacesContext".  You use the "ExpressionFactory" from the "Application" to create the MethodExpression.

So here's the code to create the ActionListenerExpression.

       /\*\*
\* Create the MethodExpressions for the Hyperlinks
\*/

/\*\*
\* First get the ExpressionFactory from the Application
\*/

ExpressionFactory expressionFactory = this.getApplication().getExpressionFactory();

/\*\*
\* Next get the ELContext
\*/

ELContext elContext = FacesContext.getCurrentInstance().getELContext();

/\*\*
\* Now create the MethodExpressions
\*/
MethodExpression listenerMethod = expressionFactory.createMethodExpression(elContext,
"#{Page1.category_action}",
null,
new Class[] {ActionEvent.class});

MethodExpression actionMethod = expressionFactory.createMethodExpression(elContext,
"#{Page1.category_action}",
String.class,
new Class[] {});

dynamicHyperlink1.setActionListenerExpression(listenerMethod);
dynamicHyperlink1.setActionExpression(actionMethod);
dynamicHyperlink2.setActionListenerExpression(listenerMethod);
dynamicHyperlink2.setActionExpression(actionMethod);
dynamicHyperlink3.setActionListenerExpression(listenerMethod);
dynamicHyperlink3.setActionExpression(actionMethod);
Lastly, you need to create the methods that will be invoked by clicking the link.  These methods will go on the page bean.  

Let me talk about the "createMethodExpression" method signature for a moment because that's important for understanding the methods.

The first parameter is the ELContext.  We've already discussed that.

The second parameter is the binding expression.  If you look at the code above, you'll see that the page is hard coded in the binding expression.
#{Page1.category_action}
You will also notice the method name "category_action".  

The third parameter is the method return type.  You'll notice in the code above for the ActionListener, we don't define a return type.  For the Action we do define a "String".  This method signature, "String action_method()" called by an action will cause JavaServer Faces navigation to check the outcome to see if a navigate is needed.

The fourth parameter of the "createMethodExpression" call is the list of arguments that will be passed to the method.  Again notice for the ActionListener the "ActionEvent" is passed.  Remember this is how we will pass data.

Here are the methods you need to define on the page.

    public String category_action() {
return "page2";
}

public void category_action(ActionEvent ae) {
String selectedListName = ((Hyperlink)ae.getComponent()).getType();
getRequestBean1().setSelectedList(selectedListName);
return;
}

You can see the "return "page2"" in the Action method.  This corresponds to this navigation file which will cause a page navigation to "Page2".

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<navigation-rule>
<from-view-id>/Page1.jsp</from-view-id>
<navigation-case>
<from-outcome>page2</from-outcome>
<to-view-id>/Page2.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/Page2.jsp</from-view-id>
<navigation-case>
<from-outcome>case1</from-outcome>
<to-view-id>/Page1.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

Conclusion

So here's what the page will look like.

dynalink1

In my next blog, I'll use this blog and the previous blog to show you how to create a "tag cloud".

You can download my sample "DynamicHyperlinks" project to get started.  As before, I used NetBeans 5.5 with Visual Web Pack.


Comments:

Very good article. Can this approach be applied to a page bean obtaining events from page fragment beans? Can you point me to some resources and examples.

Thanks,

Chris

Posted by Chris on January 13, 2008 at 08:02 AM MST #

Thanks! It helped my a lot. Jan

Posted by Jan on October 01, 2008 at 07:26 AM MDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

David Botterill

Search

Archives
« May 2015
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
31
      
Today