The ICEfaces Tutorial
Table of Contents


Lesson: Creating a Tree Using JAXB

How to Create a Tree Using JAXB

First Off, What is JAXB?

JAXB stands for Java Architecture for XML Binding. It allows for the coupling of Java and XML. This means you can access data from XML documents from applications written in Java. This particularly comes in handy for creating schema driven UI's. It allows you to set up all the information in your UI within the XML document, which allows for easier changing of your content.

The Tree

One of the more versatile and appealing components in ICEFaces is the tree component. This tutorial will show you how to set up a tree to use as a menu based on information derived from an XML document. We will use the information in the XML to not only create our tree, but will also use the tree to display the information contained in the XML document.

Accessing the XML Document

In this tutorial we will create a web application to access and display the data in treeDocument.xml. This document contains information about a fleet of ships, such as name, registry, crew size, and ship type.

Schema

First you have to have an accompanying schema. An xml schema is in the form of an .sxd document and s an XML specification that governs the allowable components of an XML document and the relationships between the components. Basically, it outlines the elements that can appear in an xml document and in which order they can appear, what attributes they can have, and which elements are subordinate. JAXB requires that the schema document be written in the WC3 Schema Language. The schema we will be using for this tutorial is treeDocument.xsd. It defines a <Fleet> as an element that has a complex type. This means that it has child elements, in this case <ship> elements. Each <ship> also has a complex type named <shipType>. The element has child elements sucha s <name>, <registry>, and <crewSize>.

Binding the Schema

Binding a schema involves generating a set of java classes that represent the schema. All JAXB implementations provide a tool to bind the schema. This tool is can invoked a number of different ways depending on the implementation. For this tutorial we will use the command line to execute the jar method (for other methods see the help files that come with JAXB). There are different ways to complete the binding process, you may copy your entire JAXB directory into your project directory, or as we will do for this tutorial, place a copy of your schema file in the JAXB/lib folder and run the following from the command line (you can copy the java files to your project directory after).

        Prompt:> java -jar jaxb-xjc.jar -p com.icesoft.icefaces.resource.tutorial.component.jaxb treeDocument.xsd -d src
        

The -p identifies the a package for the generated classes, and the -d option identifies a target directory. So for this tutorial the classes are packaged in com.icesoft.icefaces.resource.tutorial.componet.jaxb within the src directory. Once the command is executed, the compiler generates the following classes based on the treeDocument.xsd schema:

            Fleet.java
            ObjectFactory.java
            ShipFleetType.java
            ShipType.java
        

Download the demo:

Unmarshalling the Document

Unamrshalling the document means creating a tree of content objects that represents the organization of the document.

To unmarshal a document you:

Create a JAXBContext object. This provides the entry point to the JAXB API. When you create this object you must identify a context path, which defines the packages where the classes generated by the compiler are contained.

            Import. Javax.xml.bind.JAXBContext;

            JAXBContext jc = JAXBContext,newInstance(?com.icesoft.icefaces.resource.tutorial.component.jaxb?);
        

Create an Unmarshaller object. This object contains methods that perform the the actual unmarshalling operation.

            import javax.sml.bind.Unmarshaller;

            Unmarshaller unmarshaller = jc.createUnmarshaller();
            

Call the unmarshal() method. This method is what actually unmarshalls the xml document.

            Fleet fleet = (Fleet)unmarshaller.unmarshal(new File(?treeDocument.xml?));

        

You have a choice as making a separate class to be used as a JAXB manager, or you can insert this code straight into your programs main bean. For the purposes of this tutorial, we will insert it in the treeBean class as a static block.

            static{
                try {

                    jc = JAXBContext.newInstance("com.icesoft.icefaces.resource.tutorial.component.jaxb");

                    unmarshaller = (Unmarshaller)jc.createUnmarshaller();

                    fleet = (Fleet)unmarshaller.unmarshal(new File("treeDocument.xml"));

                } catch (JAXBException ex) {
                    ex.printStackTrace();
                    }

            }
        

Download the demo:

Backing Bean and Tree Setup

Once the unmarshalling is complete, you can access the data using standard getters that were created by the compiler. For this tutorial, we create 2 ship objects from a list of ships gathered from the data:

             public treeBean() {

                Fleet.Ships shipType = fleet.getShips();
                ArrayList shipList = (ArrayList)shipType.getShip();
                ship1 = (ShipType)shipList.get(0);
                ship2 = (ShipType)shipList.get(1);

                ....
            }
        

Once you have created the Ship objects, its time to put them into nodes on the tree. We start by creating a root node names ?Fleet? (be sure to create your UrlNodeUserObject class first ? see source code):

            public treeBean(){
                ....

                // create root node with its children expanded
                rootTreeNode = new DefaultMutableTreeNode();
                UrlNodeUserObject rootObject = new UrlNodeUserObject(rootTreeNode);
                rootObject.setText("Fleet");
                rootObject.setUrl("");
                rootObject.setExpanded(true);
                rootTreeNode.setUserObject(rootObject);

                ....
            }
        

Then, add each ship as a new node:

            public treeBean(){

                ....


                // model is accessed by by the ice:tree component
                model = new DefaultTreeModel(rootTreeNode);

                // add Ship1 child node
                DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
                UrlNodeUserObject branchObject = new UrlNodeUserObject(branchNode);
                branchObject.setText(ship1.getName());
                branchNode.setUserObject(branchObject);
                rootTreeNode.add(branchNode);

                // add Ship2 child node
                branchNode = new DefaultMutableTreeNode();
                branchObject = new UrlNodeUserObject(branchNode);
                branchObject.setText(ship2.getName());
                branchNode.setUserObject(branchObject);
                rootTreeNode.add(branchNode);

                ....
            }
        

Download the demo:

JSP Page and Tree Setup

Now its time to create the tree in the JSP page. Since our tree will be controlling a panelStack, we are going to use commandLinks as the nodes, and insert a param

tag in order to reference the different panels. The code snippet looks something like such:

    <ice:panelGroup styleClass="treeContainer">

    	<ice:tree id="tree"
        	value="#{treeBean.model}"
        	var="item"
        	hideRootNode="false"
        	hideNavigation="false"
        	imageDir="./xmlhttp/css/xp/css-images/" >
        	<ice:treeNode>
        		<f:facet name="content">
        			<ice:panelGroup style="display: inline">

        				<ice:commandLink value="#{item.userObject.text}"
        					actionListener="#{panelStack.selectedPanelChangedAction}" style="font-weight:bold;
        					border:1px solid black; padding-right:2px; padding-left:2px;background-color:#ccd269" >
        						<f:param value="#{item.userObject.text}" name="ships"/>
        				</ice:commandLink>

        			</ice:panelGroup>
        		</f:facet>
        	</ice:treeNode>
        </ice:tree>

    </ice:panelGroup>
        

Now you must also tie this in with the panelStack backing bean(see source code) using the selectedPanelChangedAction() method:

            public void selectedPanelChangedAction(ActionEvent event){

                FacesContext context = FacesContext.getCurrentInstance();
                Map map = context.getExternalContext().getRequestParameterMap();
                selectedPanel = (String) map.get("ships");

            }
        

Our next step is to create the panel stack. This is where we will use the Ship objects in the treeBean to display their data to the user. We will only show you the Fleet panel and the USS-JAXB panel, but subsequent panels are set up in the same matter. Notice for the values we wish to display, we can simply call the getter methods from the Ship objects we created in the treeBean.

            <ice:panelStack selectedPanel="#{panelStack.selectedPanel}" >

                 <ice:panelGroup id="Fleet">
                    <ice:outputText value="The 31st Exploratory Fleet" style="font-weight:bold; border:1px solid black;
                         background-color:#a4bdd2; padding-right:2px; padding-left:2px"/>
                    <br/><br/>
                    <ice:panelGroup style=" border:1px solid black; background-color:#a6a7a9; padding-right:2px; padding-left:2px">
                        <ice:outputText value="This Fleet contains 2 ships: the USS-JAXB and the USS-ICE.
                                                    Both are highly advanced and useful in many different scenarios. Use the tree links on the left to
                                                    see the details of the different ships." />
                    </ice:panelGroup>
                 </ice:panelGroup>

                 <ice:panelGroup id="USS-JAXB">
                    <ice:outputText value="Name:" style="font-weight:bold; border:1px solid black; background-color:#a4bdd2;
                        padding-right:2px; padding-left:2px"/>
                    <ice:outputText value="#{treeBean.ship1.name}" style="border:1px solid black; background-color:#a6a7a9;
                        padding-right:2px; padding-left:2px"/>
                    <br/><br/>
                    <ice:outputText value="Registry:" style="font-weight:bold; border:1px solid black; background-color:#a4bdd2; padding-right:2px;
                        padding-left:2px"/>
                    <ice:outputText value="#{treeBean.ship1.registry}" style="border:1px solid black; background-color:#a6a7a9;
                        padding-right:2px; padding-left:2px"/>
                    <br/><br/>
                    <ice:outputText value="Crew Size:" style="font-weight:bold; border:1px solid black; background-color:#a4bdd2; padding-right:2px;
                        padding-left:2px"/>
                    <ice:outputText value="#{treeBean.ship1.crewSize}" style="border:1px solid black; background-color:#a6a7a9;
                        padding-right:2px; padding-left:2px"/>
                    <br/><br/>
                    <ice:outputText value="Description:" style="font-weight:bold; border:1px solid black; background-color:#a4bdd2; padding-right:2px;
                        padding-left:2px"/>
                    <ice:outputText value="#{treeBean.ship1.description}" style="border:1px solid black; background-color:#a6a7a9;
                        padding-right:2px; padding-left:2px"/>
                    <br/><br/>
                    <ice:outputText value="Ship Type:" style="font-weight:bold; border:1px solid black; background-color:#a4bdd2; padding-right:2px;
                        padding-left:2px"/>
                    <ice:outputText value="#{treeBean.ship1.shipFleetType}" style="border:1px solid black; background-color:#a6a7a9;
                        padding-right:2px;  padding-left:2px"/>
                </ice:panelGroup>
        

Download the demo:

Conclusion

As you can see from this tutorial schema driven UI's are very favourable due to the fact that the data is so easy to change and manipulate. JAXB provides the perfect bridge to create a schema UI in java. Ensure your treeDocument.xml is in the path you specified in the treeBean:

             fleet = (Fleet)unmarshaller.unmarshal(new File("treeDocument.xml"));
        

You should be good to go! Note that now you can change the data displayed and the content of your tree by simply changing the information in the treeDocument.xml file.


The ICEfaces Tutorial
Table of Contents

Copyright 2006 ICEsoft Technologies Inc. All rights reserved.