36
MASARYK UNIVERSITY FACULTY OF I NFORMATICS Create a JSF component to work with map servers BACHELOR THESIS Ján Ferko Brno, Spring 2011

Create a JSF component to work with map servers - Muni - Masaryk

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

}w !"#$%&'()+,-./012345<yA| Create a JSF component to work with
map servers
BACHELOR THESIS
Ján Ferko
Declaration
Hereby I declare, that this paper is my original authorial work, which I have worked out by my own. All sources, references and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source.
Advisor: Mgr. Marek Grác
ii
Acknowledgement
I am very grateful to my supervisor Mgr. Marek Grác for his support and help throughtout my work on this thesis. I would also like to thank Lukáš Fryc from Red Hat Czech for his guidance and advice about component development in JavaServer Faces framework.
Many thanks also belong to my family and friends who have supported me for last 21 years. It would be difficult to finish work without their support.
iii
Abstract
This bachelor thesis deals with implementation of JavaServer Faces component to work with map servers. Thesis aims to simplify usage of maps in JavaServer Faces. JavaServer Faces is component-centric web framework on Java platform. It is based on MVC architecture and it is part of J2EE 6 specification. Map servers provide API to access their functionality in Javascript. This thesis focuses on connecting JSF architecture and map servers API. It aims to implement common features of all analyzed map servers, so it is easy for library client to switch from one map server to other.
iv
Keywords
JavaServer Faces, Maps, Custom Components, Javascript, Java, J2EE 6, Web Applications
v
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 JavaServer Faces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 Request Processing Lifecycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 UI Components Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3 Event Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.4 Facelets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.5 Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 Custom UI Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1 Composite Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.2 The Composite Components Implicit Object . . . . . . . . . . . . . . . . . . . . 9 3.3 Composite Component Tag Library Declaration . . . . . . . . . . . . . . . . . 10 3.4 Non-composite Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.5 State Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4 Map Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.1 Google Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1.1 Map Object and Interaction with user . . . . . . . . . . . . . . . . . . . 13 4.1.2 Overlays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.1.3 Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2 Mapy.cz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.2.1 Map Object and Interaction with user . . . . . . . . . . . . . . . . . . . 16 4.2.2 Overlays and Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.3 Bing Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.3.1 Map Object and Interaction with user . . . . . . . . . . . . . . . . . . . 18 4.3.2 Overlays and Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5 Design and Implementation of Component Library . . . . . . . . . . . . . . . . . 20 5.1 Specification of requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 5.2 Library Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.3 Javascript library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.4 Loading map servers API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.5 Components Development Kit . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.6 Abstract Component Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 5.7 Component Renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 A Content of attached CD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
vi
Introduction
With increasing accessibility and popularity of Internet in recent years, people send more data on Internet and they simultaneously increase demands on web applications. Maps servers provide services for design, implementation and delivery of maps over Internet [7]. They are one of the most popular web applications. Application allows users to explore maps of the world in different zoom levels, it offers directions planners for multiple type of transportation, e.g by driving, on foot or by public transportation. It provides information about local services and shop locations, which are shown to user directly in city map. Some servers also provide satellite or panoramatic images.
Map servers use JavaScript programming language and AJAX (Asynchronous Javascript and XML) technology. AJAX allows better interaction between user and map, because map do not have to be downloaded at once during loading the page, but every square of map grid is downloaded separately based on user map movement [6]. However usage of JavaScript also brings disadvantages for programmers of web applications. Programmer has to add JavaScript code into part of application, which is responsible for dynamic generation of web page and is written in different programming language. This issue makes code less readable and manageable and it also makes error searching and reparation more difficult.
Therefore new tools and design patterns are developed to make web applications de- velopment easier and more effective. Most programming languages provide libraries, so programmer does not have to write any JavaScript code. One of these frameworks is web framework JavaServer Faces (JSF). JSF is MVC (model – view – controller) framework [4], based on component design of user interface [3]. JSF provides UI components, templates system called Facelets, event management, AJAX support and navigation system for dy- namic redirection from one page to another. One of the main advantages of JSF is possibility to create custom components.
This thesis discusses design and implementation of custom components in JSF frame- work. Thesis describes the best practice of custom components development. Thesis also discusses features of map servers, their common and different properties. The main pur- pose of thesis was to design and implement new JSF component, which integrates map servers Google Maps1, Bing Maps2 and Mapy.cz3. Component accesses all map servers by its application programming interface (API) in JavaScript. Connecting JavaScript API and
1. Google Maps <http://code.google.com/intl/sk/apis/maps/index.html> 2. Bing Maps <http://msdn.microsoft.com/en-us/library/gg427610.aspx> 3. Mapy.cz <http://beta.api.mapy.cz/>
1. INTRODUCTION
JSF component written in Java was one of key aspects of development. Therefore we wrote common JavaScript interface to access all map servers features. Component development uses concepts of composite components [1] and also component creation techniques, which were used before release of JSF 2.0.
Chapter 1 provides introduction to JavaServer Faces. It explains request lifecycle of JSF pages, UI component tree and event handling. It describes interface, which is used to work with AJAX and declarative template language called Facelets. Chapter 2 deals with custom components development, it explains basic principles of component creation. Chapter de- scribes composite component concept and techniques of non-composite components deve- lopment by implementing appropriate JSF interfaces. Third chapter compares attributes and functionality of different map servers. Forth chapter describes design and implementation of component library with Richfaces Component Development Kit.
Bachelor thesis successfully implemented basic functionality of map servers into JSF component library. But component currently does not support all features, which are offered by map servers. Design puts emphasis on implementation of common features of Google Maps, Bing Maps and Mapy.cz map servers. We designed common Javascript interface to map server API, so provides the easiest possible way to work with maps and to switch be- tween different servers. Library may be extended to support server-side events and may add support for more map server services.
2
Chapter 2
JavaServer Faces
JavaServer Faces is web framework for Java and it is part of JavaEE 6 under JSR 314 specifi- cation1. Framework is used to build user interface of web application. Its main purpose is to define user interface in cleaner and easier way, so developer do not need to work with HTTP (Hypertext Transfer Protocol) request and response. Instead JSF processes them and it pro- vides more abstract programming model, which hides HTTP protocol under its API. It uses MVC design pattern to define and separate user interface from application logic. User inter- faces is defined in XML(Extensible markup language) tags either in JSP(Java server pages) or in XHTML pages called Facelets. Business logic is written in standard JavaBean2 classes. It is component-driven framework. Pages consist of special tags, which represent components and which are processed by FacesServlet, which takes care of calling application logic and mapping components to HTML markup. JavaServer Faces are usually used with AJAX and other Rich Internet Application technologies to make application more interactive.
This chapter provides brief description of JavaServer Faces key features, which are im- portant for building custom components. It explains JSF request lifecycle, which is respon- sible for request processing. It introduces Facelets view language, which is used to define user interface of application. It explains UI component tree, event model and it provides introduction to JSF AJAX support.
2.1 Request Processing Lifecycle
Standard way to manage web requests involves providing context for request, processing request parameters, map them to application objects, invoking business logic, which can consist of tasks such as calling database queries or web services, receiving new state from application and rendering new page based on that state. These tasks are boilerplate of every web application and they usually cause mistakes and are difficult to maintain. JSF request lifecycle provides “behind-the-scene” engine, which is responsible for managing UI compo- nents, server-side state and request context so web developer can focus on problems, which have to be solved and not technical details of HTTP protocol. It is the most important part of JavaServer Faces, because it is engine that makes it possible [1].
1. JSF Specification JSR 314 <http://www.jcp.org/en/jsr/detail?id=314> 2. Oracle introduction to JavaBeans <http://download.oracle.com/javase/tutorial/javabeans/ index.html>
3
2.1. REQUEST PROCESSING LIFECYCLE
JSF differs from other web frameworks like Struts3 or Stripes4, which still needs some request management on developer side in ActionBeans and data processing is done in lower level way than in JSF. Request lifecycle has ability to synchronize JavaBeans properties with client side UI by managing hierarchical UI component tree to which JavaBean properties are mapped on. This capability is called state management.
Figure 2.1: Request lifecycle diagram. Source: JSR 314 Section 2
JSF request processing consists of five phases:
• Restore View
• Invoke Application
• Render Response
Restore View phase restores or creates a server-side component tree (View) in memory to represent the UI information from a client [1]. If view existed in previous transactions it will be restored from memory. This usually happens after AJAX calls. If view does not exist component tree is created. After view is restored it is set to container called FacesContext, which encapsulates view and request, so requests could not be mixed from different client requests.
3. Structs framework <http://struts.apache.org/1.x/index.html> 4. Stripes framework <http://www.stripesframework.org/display/stripes/Home>
2.2. UI COMPONENTS TREE
Apply Request Values phase performs job of processing the incoming request values [1]. Each UI component is able to receive data from the user in this phase. Only components which can hold values are processed in this phase. Request values are mapped on server- side components by calling processDecodes method on root of component tree, which calls decoding methods of children components.
Process Validations phase is phase, where all conversions and validations are performed [1]. Conversion and validation can be performed by Convertor (Validator) classes or custom conversion (validation) method can be attached to component by expression lan- guage. In this phase processValidators method is executed on component, this method invokes any convertor (validator) attached to component. If component does not pass vali- dation, validator will set its valid property to false.
Update Value phase performs value mapping on JavaBeans. In this phase processUp- dates method is called on value holder components. This method invokes setter methods of model and sets new values to model.
Invoke Application phase is phase, when any application logic is called. This is done by method which is binded to action source component, such as UICommandButton. Behind the scene processApplication method is invoked on view root. This method broadcasts to every component and it fires action event which is binded to component.
Last phase of Request Lifecycle is Render Response phase. This phase renders new page view and it also prepares all static resources, such as images or scripts which are associated with page. Each component is rendered by invoking encode method and after that whole page is sent to client.
2.2 UI Components Tree
A User Interface(UI) component is a specific type of component that displays user interface content which can be modified by user over time [1]. This content can be anything from in- put fields to data grids. In JSF, UI component is every class, which extends UIComponent. This class provides core features, that every component has to have. In fact, JSF compo- nent usually consists of class than inherits UIComponent, Renderer, which is responsible for rendering markup of component, TagHandler which provides Facelets tag binding for component and helper classes such as validators, convertors and behavior classes. Helper classes provide additional functionality and are also considered to be components but are not UI components as they alone do not provide visual user interface content. UICompo- nent subclass represents abstract meaning of component and component logic should be written here. Renderer encapsulates code that renders component markup for client. Every component can have multiple renderers, each renderer for different types of client.
UI components are supposed to be primary point by which JSF are extended as they can provide various and very specific tasks-based functionality such as geomapping. Therefore it is necessary to have knowledge about interfaces and classes which are used during deve- lopment of custom components. In next parts of this section we describe various interfaces and abstract classes which can be used for component development.
5
Figure 2.2: UI Components Class Diagram
As we mentioned in previous section about JSF Request Processing Lifecycle, there are two types of components. Components that initiates an action, such as command button or command link and components which stores or provides values, such as input field or data grid. UI components that fire actions implements ActionSource2 interface, this in- terface provides methods which invoke application logic which is binded to component. Components that store data, implement either EditableValueHolder or ValueHolder interface, these two interfaces both provide ability to store data values, but only Edita- bleValueHolder interface allows users to edit values. All Converters and Validators im- plement PartialStateHolder interface, this interface allows them to save state between multiple requests. Apart from implementing behavioral interfaces components usually in- herit UIComponentBase class, which provides implementation of most of methods from UIComponent interface.
In Request Processing Lifecycle section of this chapter we explained that FacesServlet restores UI Component Tree in Restore View phase. View of page provides server-side set of components, which is used to synchronize state between client and server. After component model values are updated and Component Tree is modified it is rerendered and sent back to the client in Render Response phase. It is important to know that component tree does not reflect class hierarchy of components, it is component layout of page. It contains component instances. Every component tree consists of UIViewRoot component, which represents root of view. Tree structure of view allows every component to access its parent and children. This means that every component can be processed by single operation on UIViewRoot
6
2.3. EVENT MODEL
such as processUpdate in Apply Values phase. UI Component Tree is managed by ViewHandler between requests. However State-
Handler is responsible for preserving tree between subsequent request [1]. Component tree can be stored by several save methods either on client side or server side.
2.3 Event Model
JavaServer Faces provides event–listener programming model which is very similar to thick client frameworks like Swing5. This approach provides better control of user interface and it makes application more interactive6. The framework specifies a set of events, each with its own meaning regarding to the state of the application [1]. When event is fired by application it calls registered listeners, which executes an action to the event.
JSF provides two kinds of events:
• application events
• phase events
Application events are events which react to changes in user interface such as click on but- ton. They can be divided into two categories that are connected with UI component types that were described in previous section.
Components which implement ActionSource2 interface provide action events and ac- tion listeners. This events are fired after action is triggered on component. Once event is fired it is placed into component event queue where it waits to be processed. All action events are processed in Invoke Application phase. Action listener is either action method or action listener method. Action method is any method placed in managed bean(JavaBean) and is binded to action attribute of component. It returns string, which is then used by naviga- tion mechanism to take user to next page. Action listener methods are methods in managed bean that get ActionEvent instance as their parameter and are binded to actionListener attribute. ActionEvent attribute can be used to get more information about component that trigered event. Components which implements EditableValueHolder can react to the value change events. Behind the scene, value change events are processed in the same way as the action events, but they are binded to valueChangeListener attribute of component.
Second type of Faces events are phase events. Phase events allow user to react to certain phase of request processing. Phase events can be used to alter or extend values in different phases of lifecycle. Phase events provide access to every property, which is processed and are not attached to any concrete component.
5. Swing Event Model <http://download.oracle.com/javase/tutorial/uiswing/events/ index.html> 6. Event-driven programming <http://en.wikipedia.org/wiki/Event-driven_programming>
2.4. FACELETS
2.4 Facelets
Facelets language is primary view handler mechanism or view declarative language used in JSF 2.0. It enables defining the view of page. Facelets declares view in valid XML document. It fully supports JSF UI components as well as it builds component tree. FaceletView- Handler is responsible for creating of UIViewRoot in new view. After UIViewRoot is created view handler populates view with components and component tree is stored so it can be used afterwards and view is rendered in response. After user sent second request, e.g submiting form, view is restored and request lifecycle processes request. Before rendering response, facelet handler is used to repopulate full component tree.
One of the biggest advantage of Facelets in comparison to JSP (Java Server Pages) lan- guage is that it supports templating. Templating enables to divide view into more, smaller parts which are reusable across different pages. This makes web pages more readable, as there is less code per one page, and easier to maintain as common parts of pages are de- clared only once in view template, which means that possible mistakes in code can be cor- rected from one place.
2.5 Ajax
AJAX7 or Asynchronous Javascript and XML is term that is used to describe technique which allows developer to create more interactive web applications. AJAX is based on con- cept that certain parts of page can be refresh asynchronously, so there is no need to re- fresh whole page at once. AJAX sends request from client to server in background via Xml- HttpRequest Javascript object. This request is processed by server and new data are sent to client, where Javascript updates part of page with new markup.
JavaServer Faces provides abstract model on top of this concept so there is no need to write additional Javascript code. In most cases the only change, that is needed, is addition of <f:ajax> tag to component. This tag is responsible for asynchronous processing of compo- nent. Ajax tag also provides optional attributes which can specify details of AJAX call, such as different component to be updated or which events triggers AJAX calls.
AJAX tag binds javascript code, which calls server, to component. This code is part of Standard JSF Javascript library, which is part of every JSF implementation [1]. Once user takes action on component, Javascript function jsf.ajax.request is executed. This func- tion sends XmlHttpRequest to server and request is processed by request lifecycle. Re- quest is captured into PartialViewContext, which stores information provided in re- quest. Once request is processed, response is sent to the client and Javascript library invokes callback function, which updates page markup.
7. AJAX technology <http://en.wikipedia.org/wiki/Ajax_(programming)>
Custom UI Components
One of the most important JavaServer Faces features is its extensibility. JavaServer Faces provide environment to create custom components, which satisfied specific requirements of different web application. JSF 2.0 brings new way of building custom components called composite components. This chapter briefly explains concept of building composite compo- nents. It also describes how to build non-composite components and provides brief overview of all parts which are used to build UI component.
3.1 Composite Components
JSF component is set of elements which describes its state and behavior. Composite compo- nents model allows programmer to build component from smaller, existing pieces by con- necting them together. Composite component concept greatly benefits from Facelets as it allows component programmer to create component in declarative way. Composite compo- nent development respects Smalltalk Composite Method pattern1, which says that software should be divided into smaller methods which do single task at one level of abstraction [2]. JSF encourages programmers to compose view part of application from small fragments, so that functionality is well encapsulated.
Composite component consists of two parts – interface and implementation. Interface declares abstraction or contract of component. Interface declares information about compo- nent, which are needed for client to access component functionality. It is interface section where all attributes and events are declared. Implementation provides component’s imple- mentation. It consists of composition of subcomponents and binds properties which are declared in interface to them.
Composite component is not distinct from native JSF UI component. It can have events attached, it can declare child content or facet. It can be used in same way as non-composite component [1].
3.2 The Composite Components Implicit Object
This object resolves to the top-level component for the defining page in which expression appears[1]. Top level component in case of composite component is UINamingContainer.
1. Composite method pattern <http://en.wikipedia.org/wiki/Composite_pattern>
3.3. COMPOSITE COMPONENT TAG LIBRARY DECLARATION
This means that Custom Components (cc) implicit object provides access to information from UIComponent class, such as clientId. This object is used to access declared attributes by its attrs property.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:cc="http://java.sun.com/jsf/composite">
<cc:attribute name="title" required="false" shortDescription="Logo title" />
<cc:attribute name="link" required="true" /> </cc:interface>
<!-- IMPLEMENTATION --> <cc:implementation>
<h:outputLink value="#{cc.attrs.link}" > <img src="#{cc.attrs.logoImage}" alt="#{cc.attrs.title}"
class="image"/> <h:outputText value="#{cc.attrs.title}" styleClass="title"/>
</h:outputLink> </div>
</cc:implementation> </html>
Figure 3.1: Example of simple composite component
In fragment of code above, we created simple component which represents logo panel. We declared required and optional attributes in interface section and we binded them to subcomponents in implementation part. We use “cc.attrs” property to access values of at- tributes and we also use custom stylesheet to provide appearance.
3.3 Composite Component Tag Library Declaration
Similar to Facelets, composite component tag has to be part of tag library, so that it can be used in the page. Tag library has to follow convensions for resource libraries in JSF. Compo- site components benefit from this convention, because they do not need to declare separate XML file, which defines all tags in library. Instead composite component is placed under META-INF/resource directory of application and it is part of XML namespace, which is in
10
3.4. NON-COMPOSITE COMPONENTS
specific format2. JSF runtime than treats component folder as tag library with this name- space.
3.4 Non-composite Components
Non-composite components provide different way of developing custom components. This method is part of JSF since version 1.0. It is based on providing implementation of UI- Component interface and its helper classes, such as Renderer, TagHandler and attached object like validators, convertors and event listeners. It is also necessary to implement Faces Tag Library descriptor. This development approach provides ways to implement compo- nents, which cannot be implemented as composite component because their functionality could not be divided into existing components, or because it implements functionality, which is mostly javascript based and its implementation as composite component would be more difficult. This chapter describes all subcomponents, which are required to build non-composite component.
The most essential part of every component is UIComponent subclass, which is in fact subclass of UIComponentBase. It is also possible to extend from other existing compo- nents. This is class, which contains core features and behavior of the component. It is abstract representation of component. It usually consists of getters and setters for component at- tributes and business logic, which manipulates received properties, or provides information about other components in component subtree. In addition, it could render final markup of component, but it is better practice to put methods which render markup to separate Renderer, so that component logic is decoupled from rendering code.
As we mentioned in previous section Renderer class is responsible for rendering com- ponent markup. It also contains code, which process data from incoming requests. Render- ers can provide different markup for different client devices. Process of rendering markup is called encoding in JSF. Renderer superclass provides different methods of rendering markup such as encodeBegin, encodeEnd, encodeChild. EncodeBegin method renders mark- up which should be rendered before any children components are rendered. EncodeChild encodes code which renders children components and encodeEnd encodes code after child- rens are fully rendered. Markup is produced by writing HTML tags to ResponseWriter, which is available from FacesContext. Response writer allows programmer to start and close elements and to write attributes and text of elements. Every encode method have also access to UIComponent, that it is supposed to render, so that renderer has access to busi- ness logic of component. Processing of incoming request is done by decode method. This method retrieves attribute values from request and set them to component class. Different renderers of same component can be grouped into RendererKit. RendererKit is data struc- ture, which contains instances of renderers that are registered to kit. This structure is con- sulted when JSF runtime makes decision which markup is supposed to be sent to the client.
2. Composite component library namespace format - http://java.sun.com/jsf/composite/<component_- folder>
11
3.5. STATE HANDLER
Faces Tag Library declares permitted tags and pairs them with component and renderer [1]. Library also defines namespace for each tag. Renderer and component class are iden- tified by their type, which is an unique string returned by getComponentType and ge- tRendererType. Renderer can be coupled with component only if they have same family identifier.
There are situations when page execution process needs to be controled in order to render component. This goal can be achieved by implementing custom TagHandler. Tag handler provides entry point to processing phases, when JSF runtime creates component or its children. It can be used tasks such as logging information about component state just after its creation.
3.5 State Handler
One of the problems, which needs to be addressed during JSF component development is component state saving. Before JSF 2.0, component had to implement saveState and restoreState methods which often caused errors in state processing. JSF 2.0 introduces partial state class called StateHelper, that provides simplier and less error prone way how to manage state of component. State helper is based on concept that storing entire component tree is redundant as it can be restored by rerendering view [5]. So JFS runtime only stores changes of property values.
StateHelper provides component storage for its properties so component does not have to implement saveState and restoreState methods. StateHelper is essentially key- value map where key has to implement Serializable interface and value can be any Object. UIComponent subclass defines enumeration of property keys and pairs them with values in setters to put them into StateHelper implementation. Getters methods than ac- cess StateHelper to get mapped attributes.
12
Chapter 4
Map Servers
This chapter describes features of Google1, Bing2 and Mapy.cz3 map server. It also examines capabilities of all Javascript APIs and compares their common and different functionality and characteristics from application programmer point of view.
4.1 Google Maps
Google Maps was first server, which provided map searching and exploring. At the moment API is in version 3 and it grants the widest range of features from all map servers, that were analyzed.
4.1.1 Map Object and Interaction with user
Fundamental object of API is google.maps.Map object, which represents map without any other service, layer or overlay. Map object supports multiple, configurable properties, such as different map types, initial zoom level and initial centre of the map. Programmer can prevent map from being dragged and can also set maximum and minimum possible zoom level. Google Maps differentiates four map layers – roadmap, satellite, terain and hybrid map type, which is mix of roadmap and satellite map layers. User can also add different map controls. All properties and settings are accessed via options object passed in constructor or via getter and setter methods.
Google Maps allows interaction with user via events and its listeners. API supports two types of events:
• user events,
• API object state change events (MVC events).
User events propagate operations from Document Object Model4 (DOM) of page, but events, that are provide, are internal part of API and they are not same as standard HTML events. This feature secures cross-browser compatibility.
1. Google Maps API <http://code.google.com/apis/maps/documentation/javascript/> 2. Bing Maps API <http://msdn.microsoft.com/en-us/library/gg427610.aspx> 3. Mapy.cz API <http://beta.api.mapy.cz/> 4. Document Object Model <http://www.w3.org/DOM/>
4.1. GOOGLE MAPS
MVC events represent value (state) changes in API objects, e.g. Zoom change. Google Maps events are processed by system of listeners. Event is registered by google.maps- .events.addListener method, which receives API object (such as map or marker), that event is registered on, event name and handler method, which is supposed to be called after event is fired. API supports also standard DOM events, but application looses cross- browser compatibility. Every object in API defines its own set of events, that unique for each API objects.
Google Maps API allows programmer to set different control panels on top of map. Basic control panels are:
• pan control panel,
• zoom control panel,
• and map type control panel.
Pan control panel allows user to move view of map. Zoom control panel allows user to change current zoom level. Scalebar does not interact with user, it only provides informa- tion about current scale of map in meters per centimeter on map layer. And map type control allows user to change used map layers. All controls can be modified in map options object, which is passed to map constructor. Control appearance can be change to suit different plat- forms, e.g IPhone, Android, PC. API also allows to change position of control panel. It is also possible to create custom controls.
4.1.2 Overlays
Next part of API are map overlays. Overlays are objects, which are tied to map coordinates (latitude/longitude), so they can be scaled when map is dragged or zoom level is changed. Coordinates are represented by google.maps.LatLng object. Google Maps provides 6 basic overlays:
• markers,
• polylines,
• polygons,
4.1. GOOGLE MAPS
Overlays are added to the map by using appropriate constructor and by passing map object to setMap method of constructed overlay.
Markers mark single geographic point on the map. It is possible to customize icons, to set different title, description and their position, shadow, visibility and they can be draggable and clickable.
Polylines connect multiple points on map. Coordinates of points are passed to polyline option object as array of google.maps.LatLng objects. Polylines allow to change their stroke color, opacity and weight.
Polygons are very similar to polyline, but they also fill area created by connecting given points. Polygon also connects first and last point in path array. Google allows same modifi- cation on polygons as on polylines and it is also possible to configure fill color.
Circles are defined by centre and radius instead of path array. Radius is specified in meters and centre is LatLng object. Circle properties are same as polygon properties.
Special case of overlay is ground overlay, which is rectagular image overlay. It places image on top of map in specified bounds.
Information Window is window, which shows additional information about location where it is placed. Its content can be defined in plain text or HTML code. Programmer can customize maximum width and offset.
Collection of objects adds objects retrieved from other services to map. Google Map API supports KML layer, Fusion Tables, Traffic layer and Bicycling layer.
KML layer allows data retrieval from KML5 service and GeoRSS6. API converts XML response to KML representation object and it displays point elements as markers, lines as polylines and so on. These object are drawn in one common object, which consists of meta- data from XML response and are placed in map as one distinct overlay.
Fusion Table layer comunicates with Google Fusion Table7 service, which allows to store data in tables same as relational database. Fusion overlay uses table columns with Location data type. Layer allows only data loading from tables, which are public. Data are retrieved from tables by SQL select query, that is parameter of REST(Representational State Transfer) query. Traffic layer adds real-time traffic information to map. Bicycling layer adds cycling paths to map.
4.1.3 Services
Google Maps API also provides HTTP interface to services, which adds extensive informa- tion to map. These interface consists of:
• Geocoding,
• Elevations,
• Directions,
Geocoding service translates LatLng8 object to human-readable, location address and reversely, it translates address to LatLng object. Requests are sent asynchronously and re- sults are retrieved in form of JSON object, that is processed by registered callback function. Service can reduce its searching to concrete geographical location in order to improve per- formance.
Direction service is used to calcute journey from one location to another by different transport methods. Request is sent to Google Directions Service, which computes results and sends it back to client. Request consists of place of departure, destination and transfer type. Directions service provides three transfer options - by car, hiking paths and cycling paths. Service also allows to customize road by setting mandatory waypoints. Track results are than rendered by DirectionRenderer.
Elevation service provides interface to calculate elevation data for location on surface of the earth, including depth locations on ocean floor. Street View service provides 360 degrees panoramatic view of chosen location. Service is accessed by Street View control of map. It also retrieves metadata about location.
4.2 Mapy.cz
Mapy.cz API is currently in version 4.5 beta and supports only maps of Europe, maps of other parts of the world are not supported yet. This interface differs from previous versions of API, which were more dependent on object, which represented map. Because it provided most of API functionality. New version of API uses very similar design approach to Google Maps API.
4.2.1 Map Object and Interaction with user
Map is represented by SMap object. Programmer can set center of the map, zoom level and map type. Mapy.cz provides a few different map types:
• Roadmap
It also provides maximum and minimum zoom, orientation, animation time, draggable properties. API uses SMap.Coords object to represent location. SMap.Coords object can calculate azimuth, distance, new map centre and can create location coordinates from EXIF
8. google.maps.LatLng <http://code.google.com/apis/maps/documentation/javascript/ reference.html#LatLng>
format, from pixels and from standard WGS84 (World Geodetic systém 84) format. Map ob- ject provides methods to add, remove and retrieve existing overlays of map and to add new layers, which can separate different overlays to differentiate tiers of overlays, so that they can be manipulated at once.
Mapy.cz also provides different map control components, such as pan control compo- nent, zoom control component and map type component. All components can be positioned to various places in the map window. Map type component can limit switchable layers.
Mapy.cz API also supports event handling. All map objects have method getSignals, which is essentially array of listeners that are registered to object. By calling addListener method on signals object you can register handler to component. Every component of API defines specific events, that client can react on. Mapy.cz currently does not support any kind of DOM events.
4.2.2 Overlays and Services
• Markers,
• Polylines,
• Polygons,
• Circles,
• Information Windows.
Mapy.cz API introduces concept of decorators. Decorators are Javascript objects, which add custom functionality to overlays after they are added to them. Decorators are used by calling decorate method on overlay with choosen decorator as parameter. Markers can use draggable decorator to become draggable. Marker also has Card decorator to add information window to marker, image map decorator, that adds image as marker icon and shadow decorator to add shadow efect to marker.
Markers have separated layer called SMap.Layer.Marker and can be added to either layer or directly to map. Markers can be clickable and dragability. Client can set title and image url to customize it.
Mapy.cz also introduces transparent geometry layer for polylines, polygons and circles. Geometry layer can be used for easier removal of geometry overlays and for easier redraw of graphics. Every geometrical overlay is created by SMap.Geometry constructor to which overlay type identifier is passed.
Polylines are constructed from array of SMap.Coords and can have stroke color, width and opacity changed. Polygons are constructed in very same way, but programmer can also set fill color and opacity.
17
4.3. BING MAPS
Circles are also very similar to circles used in google maps. User have to specify circle centre and radius. Information windows are called cards in Mapy.cz API and can be con- nected with marker by SMap.Marker.Feature.Card decorator, or can be added directly to map. API specifies that anchor, title, footer, description, size (both height and width) and visibility can be configured.
Only services that is provided by API is Geocoding and Reverse Geocoding. These ser- vices are used to translate SMap.Coords to address and reversely, address to SMap.Coords. Mapy.cz geocoding service does not provide any additional information about location.
4.3 Bing Maps
Bing provides additional APIs to work with maps. Presentation of map in web pages is provided by Javascript API. For proper usage of API, you have to provide credential key, received from Microsoft, to map options. Maps services, such as Geocoding or Directions are accessible by Simple Object Access Protocol (SOAP) or Representational State Transfer (REST) technology. REST API also supports journey planner for driving and hiking journeys and it also supports waypoint specification to restrict journey searching.
4.3.1 Map Object and Interaction with user
Bing Map is constructed by Microsoft.Maps.Map class. Bing Maps defines map options in two Javascript objects. MapOptions, which is responsible for setting credentials, allowing keyboard and mouse input, visibility of map controls and setting map type. ViewOptions allows user to set bounds of the map, zoom level, centre of the map, padding and whether to animate map navigation or not. Bing Maps provides these map tile layer:
• aerial layer, which is map layer with high definition images of surface,
• birdeye layer, which provides images from very small altitude,
• roadmap,
• hybrid.
Bing Maps also allows to customize the controls. It does not provide separated zoom and pan control as Google Maps or Mapy.cz, instead API creates one component, which consists of both pan and zoom control. API also supports map type control component.
Bings Maps defines specific events for every map component. Events are registered by Microsoft.Maps.Events.addHandler method, which receives map component, event name and handler function, which is called when event is fired.
4.3.2 Overlays and Services
18
• Pushpins,
• Polylines,
• Polygons,
• InfoBoxes.
All overlays have their own constructor. After overlays is constructed it can be added either to map or to custom layer. Both layer and map have array property called entities, which contains all overlays that are associated with it.
Pushpin is constructed by passing Microsoft.Maps.Location object and optional settings. Optional settings consists of icon url, title, height, width, visibility and dragga- bility indicator. Polygons and Polylines are created likewise, except for array of Micro- soft.Maps.Location is passed to constructor. User can customize Polylines and Poly- gons stroke color, width and opacity and fill color, opacity of polygons.
Bing Maps supports Directions retrieval. Directions are retrieved by Microsoft.Maps- .Map.getDirections method, which gets array of Microsoft.Maps.Location. Me- thod returns JSON9, that describes route and route waypoints.
9. JavaScript Object Notation
Design and Implementation of Component Library
This chapter analyzes requirements of map component library and proposes design layout. It explains benefits and drawbacks of chosen design. It also provides brief overview of tools used while implementing component. Next two sections describe implementation of diffe- rent, component parts, such as UIComponent subclass and renderer. It also explains how to provide binding between JSF component and Javascript library which encapsulates all map server APIs.
5.1 Specification of requirements
Goal of the thesis was to implement JavaServer Faces component library which provides access to Google Maps, Bing Maps and Mapy.cz . The library focuses on implementation of common features of each map server and it provides simple way to change different map servers in page. All choosen features are based on actual versions of map server APIs. Google Maps binding is based on Javascript API v3. Bing Maps implementation is based on API v7 and Mapy.cz implementation is based on API v4 beta. Library also aims to provide “Javascript free” componets for client, so client does not have to write any unnecessary Javascript code. Rest of this section summarizes common features of map subcomponents that are provided by library.
Map component defines map grid and allows user to set center of map, default zoom level, minimum and maximum zoom. It allows to lock map and set map tile layer. Map tile layers available in map component are roadmap layer, satellite layer, terrain layer and hy- brid layer. Center of the map is defined by latitude and logitude properties of component and these properties are required. Map component provides three implementations, one for each map server. Other components call their map server specific representation based on chosen implementation of this component, so client use only one component implementa- tion for every map server.
Map component allows to set different control panels of map. Every map server uses different control panels, so every map implementation provides different properties to set control panels. Google and Mapy.cz map servers provides separate pan and zoom controls, but Bing Maps provides only one component called dashboard which provides both pan and zoom functionality. This diference is reflected in map component.
Library provides five types of overlays:
20
• and information windows.
Marker component allows user to set position of marker based on latitude and longi- tude properties, it can set custom image and shadow. It also allows user to lock marker and disable event processing on marker.
Polylines and Polygons are defined as array of points with specific latitude and longi- tude. Points are represented by map server specific objects in all APIs. This difference is reflected in library by providing special object to define location on map. Polyline and poly- gon components require nested location components.
Polyline component allows user to customize its stroke color, stroke opacity and stroke width. Polygon component is very similar to polyline component except it connects also first and last location to create closed area. This means that component allows customization of fill color and fill opacity.
Circle component is special case of polygon, but library implements it separately. Circle is specified by its center latitude and longitude and radius. Circle radius is integer which represents radius in meter units. Circle component has same configuration options as poly- gon.
Information Window component can be connected to marker or it can be binded directly to the location on map. It is possible to set its visibility, title, width and offset. Its content can be plain text or HTML code.
The only service provided by all map servers is Geocoding. Google Maps and Bing Maps also provides Direction service and 3D view, called street view in Google Maps. Google Maps also provides integration with Fusion Table.
5.2 Library Structure
The library structure follows Maven standard directory layout1 and it uses Maven for de- pendency and build management. Every component consists of abstract class and renderer base class. Abstract class implements all business methods and is subclass of UICompo- nentBase class. RendererBase is subclass of Renderer and it implements helper methods which provides information from component class for renderer template.
Renderer templates are placed in src/main/templates directory and they provide markup templates for Component Development Kit, which renders RendererBase subclass that is
1. Maven Standard Directory Layout <http://maven.apache.org/guides/introduction/ introduction-to-the-standard-directory-layout.html>
used as component renderer. Resource directory contains Javascript library, which provides common interface for all map APIs and it also contains utility function which are responsible for adding specific API resources to the page.
5.3 Javascript library
Because component library does not provide new functionality, instead it binds existing functionality of map servers, provided throught their Javascript API, with JSF, it was necce- sary to implement Javascript library which is used as common interface for accessing diffe- rent APIs. Javascript library uses module pattern2. This pattern emulates classes in Javascript. It encapsulates functionality and allows programmer to define private and public members of object and client has limited access to information inside module. This concept is used to hide map server specific object until it requested from component renderer. This provides certain level of safety and control over resource creation.
Every map object is defined in namespace Muni.[component_name] and map object implementations for different map servers are placed in object named by map server iden- tifier (either google, bing or seznam). Every object uses following prototype:
function MapComponent{ var existingComponents = []; return {
add: function(cfg[,map]){ //add component
},
},
} }
}
Figure 5.1: Prototype of map component javascript binding
Add method uses provided configuration object to create component. Every component has it is own configuration object which reflects its requirements. First, provided configura- tion object is merged with default settings than it is converted into options object specific for
2. Javascript Design Patterns <http://addyosmani.com/resources/essentialjsdesignpatterns/ book/#designpatternsjavascript>
5.3. JAVASCRIPT LIBRARY
every map server, or is used by map specific object. After component is successfully created it is saved into array of existing objects and method returns its reference to client. Add me- thod also has optional map attribute which is used to add map subcomponent to existing map. Remove method removes object provided as attribute from array of existing objects and from map. Code fragment above shows implementation of Marker component binding in google.Marker module:
Muni.Marker.google = (function(){ var markers = [];
return { addMarker: function(map, cfg){
.LatLng(options.latitude, options.longitude); var markerOptions = {
} if(options.image != null && options.image != ""){
},
markers.splice(idx, 1); }
})();
5.4 Loading map servers API
As mentioned in chapter 2 every JSF page has to be valid XHTML document. According to XHTML specification3 it is not possible to use document.write() function in XHTML page. Since XHTML is XML (eXtensible Markup Language) and markup cannot be added while parser is still parsing document. This loading method caused problems when compo- nent library tried to append map server API to document as static resource. Because map server API uses document.write to add additional scripts which are used internally in map. Problem can be resolved by appending scripts asynchronously after page is loaded.
Figure 5.4.1 shows method how to load API asynchronously to page. Function initApi creates new script tag and sets its source to URL, where API is located. API url qury pa- rameter is used to set callback function. This function is called after API is fully loaded. Initilization function is registered to window.onload event in map renderer. Onload event is trigered after page is loaded so API loader can use document.write() to scripts. Map renderer contains logic that calls initialization method only if map server API has not been loaded, otherwise it calls callback function directly.
function initApi(callback){ var scriptUrl = "http://maps.google.com/maps/api/js?
sensor=true&callback=" + callback; var script = document.createElement("script"); script.type = "text/javascript"; script.src = scriptUrl; $(’head’).append(script);
}
5.5 Components Development Kit
Chapter 3 explained, that creating non-composite component requires implementation of UIComponent subclass, creating Renderer and taglib.xml descriptor, faces-config.xml de- scriptor, provide custom TagHandler and attached objects. This process requires to create lot of “boilerplate” code, which is used to connect particular parts of component together. Writing component markup in Java ResponseWriter is source of errors and it is difficult to maintain.
3. XHTML Specification <http://www.w3.org/TR/xhtml1/>
5.6. ABSTRACT COMPONENT CLASS
That is reason why map component library uses Richfaces Component Development Kit (CDK)4 to create components. CDK generates whole “boilerplate” code, so developer can focus on component logic. Developer only creates UIComponent subclass and Renderer. CDK generates taglib.xml, TagHandler and faces-config.xml for component. CDK also pro- vides templating facility to make renderer implementation easier.
5.6 Abstract Component Class
As it was mentioned in chapter 3 every component has to implement UIComponent inter- face or be subclass of other component which implements this interface. Each library com- ponent is in fact subclass of UIComponentBase. But CDK makes process of creating this class easier. In normal JSF component every property has to use StateHelper structure to save its properties between requests. CDK provides annotations which are used by CDK generator to generate getters and setter method.
@JSFComponent(family=AbstractMarker.FAMILY, type=AbstractMarker.TYPE, renderer=@JsfRenderer(type=MarkerRendererBase.TYPE,
family=AbstractMarker.FAMILY) ) public abstract class AbstractMarker extends UIComponentBase {
public static final String FAMILY = "cz.muni.fi.marker"; public static final String TYPE = "cz.muni.fi.marker";
@Attribute(required=true) public abstract Double getLatitude();
@Attribute(required=true) public abstract Double getLongitude();
public AbstractMap getParentMap(){ //return parent map of marker
} //rest of attributes and methods ommited
}
Figure 5.3: Marker abstract class
Every component defines its own type and family identifier. This identifiers are used in taglib descriptor to connect different parts of component and to bind component and facelets tag together. Component class is annotated by @JSFComponent annotation this annotation is used to generate component configuration. @JSFRenderer annotation binds
4. Richfaces CDK <http://www.jboss.org/richfaces>
5.7. COMPONENT RENDERER
component with renderer. All getters are annotated by @Attribute annotation. Every com- ponent also provides method that traverses UI component tree and returns parent map com- ponent. This is used in renderer to render appropriate component for different map servers. During building of component CDK generates implementations of these methods which interact with StateHelper structure.
5.7 Component Renderer
Component renderer implementations are divided in two parts RendererBase class, which provides resource dependencies and business logic methods required for correct component rendering. And renderer template which uses special CDK tag libraries5 to define compo- nent markup in very similar way to composite components.
@ResourceDependencies({ @ResourceDependency(name="marker.js", target="head")
}) public class MarkerRendererBase extends Renderer{
public String getMapServerType(UIComponent component){ //this method calls AbstractMarker.getParentMap() //to get map server type
} }
MarkerRendererBase class allocates static Javascript resources by @ResourceDe- pendecy annotation and it also implements getMapServerTypemethod, which calls com- ponent business logic method that returns map server identifier.
Renderer template is defined in XHTML and it uses special tag libraries to create final markup. Tag libraries provides standard XHTML tags, tags for renderer metadata definition such as renderer type and tags for flow control which are similar to tags in JSP core library. This fragment of code shows marker renderer template:
<cdk:root> <cc:interface>
}; var m = Muni.Marker.#{mapServer}
</cdk:root>
Renderer template is divined into two parts – interface and implementation, same as composite component definition. Interface configures renderer metadata. It sets renderer family and type. Renderer type has to be same as renderer type specified in @JSFCom- ponent annotation in abstract component class. It also sets renderer superclass to Ren- dererBase. Implementation consists of concrete implementation of component. Markup consists only from Javascript. It retrieves component attributes values by expression lan- guage and binds them to configuration object. Than it calls javascript library function within map server module which adds markup to map.
27
Conclusion
Bachelor thesis successfully implemented JavaServer Faces component library to work with different map servers. Library provided basic functionality for different map components. Library contains all widely used map components and it works with Google Maps, Bing Map and Mapy.cz. Library provides common Javascript interface for all map servers. It is focused on common features and configurations of components, so client can easily switch between different map servers.
Library can be extended to support map server events. All components in library cur- rently supports client behaviors but are not binded to javascript listeners and do not have public access attributes to set callback methods to listeners. The greatest issue in implement- ing event handling properly is reverse update of values from map to its JSF representation. One possible way to resolve this issue is to send AJAX request to server using Standard JSF Javascript Resource Library. Request should contains updated values of component proper- ties. It is also important to know, that components are not currently connected to any html element which can cause problems when updating component in AJAX callback.
Another possible improvement is to implement additional services as geocoding. It is recommended to call REST service in Java code from AbstractMap component or provide attached converter which will call geocoding service.
Library is well-documented and can be used as core tool for implementation of other features of map servers or to add other map servers. Its usage is shown in demo application which is located on attached cd or its source can be downloaded from project site.1
1. Project Page <http://code.google.com/p/maps4jsf/>
[1] BURNS, E.: JavaServer Faces 2.0 - The Complete Reference, McGraw-Hill, New York 2010, 978-0-07-1662509-8. 1, 2.1, 2.1, 2.2, 2.2, 2.3, 2.5, 3.1, 3.2, 3.4
[2] GEARY, D.: JSF 2 fu, Part 2: Templating and composite components [On- line], June 2009 [30.4.2011], <http://www.ibm.com/developerworks/java/ library/j-jsf2fu2/index.html##tip2> . 3.1
[3] ADÁMEK, P. and KUBA, M.: Java Server Faces [Online], 2008 [25.10.2010], http://kore.fi.muni.cz/wiki/index.php/Java_Server_Faces [Online] <http: //kore.fi.muni.cz/wiki/index.php/Java_Server_Faces> . 1
[4] ECKSTEIN, R.: Java SE Application Design With MVC [Online], 2007 [25.10.2010], <http://www.oracle.com/technetwork/articles/javase/ index-142890.html> . 1
[5] SCHWARTZ, A.: What’s new in JSF 2.0 [Online], July 2009 [30.4.2011], <http: //andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/ ##state-saving> . 3.5
[6] NG, M.: Google Maps [Online], 2010 [25.10.2010], <http://en.wikipedia.org/ wiki/Google_Maps> . 1
[7] NEUMANN, A.: Web Mapping [Online], January 2007 [30.4.2011], <http://en. wikipedia.org/wiki/Web_mapping> . 1
29
Attached cd contains the following items:
• a PDF version of the thesis,
• DocBook and LaTex source files, images and code examples required to compile thesis,
• component library source code
• and demo application
The PDF version of the thesis is located in folder thesis. Source files required to com- pile thesis text are also in same folder. Component library and demo application are located in project. Both component library and demo application are Maven projects and they have to be built manually. Demo application can be deploy to any J2EE application server.
30
Contents
3.4 Non-composite Components
3.5 State Handler
4 Map Servers
4.1 Google Maps
4.1.2 Overlays
4.1.3 Services
4.2 Mapy.cz
4.2.2 Overlays and Services
4.3.2 Overlays and Services
5.1 Specification of requirements
5.5 Components Development Kit
5.6 Abstract Component Class