Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Programming

1081 Articles
article-image-creating-dynamic-maps
Packt
27 Jan 2017
15 min read
Save for later

Creating Dynamic Maps

Packt
27 Jan 2017
15 min read
In this article by Joel Lawhead, author of the book, QGIS Python Programming Cookbook - Second Edition, we will cover the following recipes: Setting a transparent layer fill Using a filled marker symbol Rendering a single band raster using a color ramp algorithm Setting a feature's color using a column in a CSV file Creating a complex vector layer symbol Using an outline for font markers Using arrow symbols (For more resources related to this topic, see here.) Setting a transparent layer fill Sometimes, you may just want to display the outline of a polygon in a layer and have the insides of the polygon render transparently, so you can see the other features and background layers inside that space. For example, this technique is common with political boundaries. In this recipe, we will load a polygon layer onto the map, and then interactively change it to just an outline of the polygon. Getting ready Download the zipped shapefile and extract it to your qgis_data directory into a folder named ms from https://github.com/GeospatialPython/Learn/raw/master/Mississippi.zip. How to do it… In the following steps, we'll load a vector polygon layer, set up a properties dictionary to define the color and style, apply the properties to the layer's symbol, and repaint the layer. In Python Console, execute the following: Create the polygon layer: lyr = QgsVectorLayer("/qgis_data/ms/mississippi.shp", "Mississippi", "ogr") Load the layer onto the map: QgsMapLayerRegistry.instance().addMapLayer(lyr) Now, we’ll create the properties dictionary: properties = {} Next, set each property for the fill color, border color, border width, and a style of no meaning no-brush. Note that we’ll still set a fill color; we are just making it transparent: properties["color"] = '#289e26' properties["color_border"] = '#289e26' properties["width_border"] = '2' properties["style"] = 'no' Now, we create a new symbol and set its new property: sym = QgsFillSymbolV2.createSimple(properties) Next, we access the layer's renderer: renderer = lyr.rendererV2() Then, we set the renderer's symbol to the new symbol we created: renderer.setSymbol(sym) Finally, we repaint the layer to show the style updates: lyr.triggerRepaint() How it works… In this recipe, we used a simple dictionary to define our properties combined with the createSimple method of the QgsFillSymbolV2 class. Note that we could have changed the symbology of the layer before adding it to the canvas, but adding it first allows you to see the change take place interactively. Using a filled marker symbol A newer feature of QGIS is filled marker symbols. Filled marker symbols are powerful features that allow you to use other symbols, such as point markers, lines, and shapebursts as a fill pattern for a polygon. Filled marker symbols allow for an endless set of options for rendering a polygon. In this recipe, we'll do a very simple filled marker symbol that paints a polygon with stars. Getting ready Download the zipped shapefile and extract it to your qgis_data directory into a folder named ms from https://github.com/GeospatialPython/Learn/raw/master/Mississippi.zip. How to do it… A filled marker symbol requires us to first create the representative star point marker symbol. Then, we'll add that symbol to the filled marker symbol and change it with the layer's default symbol. Finally, we'll repaint the layer to update the symbology: First, create the layer with our polygon shapefile: lyr = QgsVectorLayer("/qgis_data/ms/mississippi.shp", "Mississippi", "ogr") Next, load the layer onto the map: QgsMapLayerRegistry.instance().addMapLayer(lyr) Now, set up the dictionary with the properties of the star marker symbol: marker_props = {} marker_props["color"] = 'red' marker_props["color_border"] = 'black' marker_props["name"] = 'star' marker_props["size"] = '3' Now, create the star marker symbol: marker = QgsMarkerSymbolV2.createSimple(marker_props) Then, we create our filled marker symbol: filled_marker = QgsPointPatternFillSymbolLayer() We need to set the horizontal and vertical spacing of the filled markers in millimeters: filled_marker.setDistanceX(4.0) filled_marker.setDistanceY(4.0) Now, we can add the simple star marker to the filled marker symbol: filled_marker.setSubSymbol(marker) Next, access the layer's renderer: renderer = lyr.rendererV2() Now, we swap the first symbol layer of the first symbol with our filled marker using zero indexes to reference them: renderer.symbols()[0].changeSymbolLayer(0, filled_marker) Finally, we repaint the layer to see the changes: lyr.triggerRepaint() Verify that the result looks similar to the following screenshot: Rendering a single band raster using a color ramp algorithm A color ramp allows you to render a raster using just a few colors to represent different ranges of cell values that have a similar meaning in order to group them. The approach that will be used in this recipe is the most common way to render elevation data. Getting ready You can download a sample DEM from https://github.com/GeospatialPython/Learn/raw/master/dem.zip, which you can unzip in a directory named rasters in your qgis_data directory. How to do it... In the following steps, we will set up objects to color a raster, create a list establishing the color ramp ranges, apply the ramp to the layer renderer, and finally, add the layer to the map. To do this, we need to perform the following: First, we import the QtGui library for color objects in Python Console: from PyQt4 import QtGui Next, we load the raster layer, as follows: lyr = QgsRasterLayer("/qgis_data/rasters/dem.asc", "DEM") Now, we create a generic raster shader object: s = QgsRasterShader() Then, we instantiate the specialized ramp shader object: c = QgsColorRampShader() We must name a type for the ramp shader. In this case, we use an INTERPOLATED shader: c.setColorRampType(QgsColorRampShader.INTERPOLATED) Now, we'll create a list of our color ramp definitions: i = [] Then, we populate the list with the color ramp values that correspond to the elevation value ranges: i.append(QgsColorRampShader.ColorRampItem(400, QtGui.QColor('#d7191c'), '400')) i.append(QgsColorRampShader.ColorRampItem(900, QtGui.QColor('#fdae61'), '900')) i.append(QgsColorRampShader.ColorRampItem(1500, QtGui.QColor('#ffffbf'), '1500')) i.append(QgsColorRampShader.ColorRampItem(2000, QtGui.QColor('#abdda4'), '2000')) i.append(QgsColorRampShader.ColorRampItem(2500, QtGui.QColor('#2b83ba'), '2500')) Now, we assign the color ramp to our shader: c.setColorRampItemList(i) Now, we tell the generic raster shader to use the color ramp: s.setRasterShaderFunction(c) Next, we create a raster renderer object with the shader: ps = QgsSingleBandPseudoColorRenderer(lyr.dataProvider(), 1, s) We assign the renderer to the raster layer: lyr.setRenderer(ps) Finally, we add the layer to the canvas in order to view it: QgsMapLayerRegistry.instance().addMapLayer(lyr) How it works… While it takes a stack of four objects to create a color ramp, this recipe demonstrates how flexible the PyQGIS API is. Typically, the more number of objects it takes to accomplish an operation in QGIS, the richer the API is, giving you the flexibility to make complex maps. Notice that in each ColorRampItem object, you specify a starting elevation value, the color, and a label as the string. The range for the color ramp ends at any value less than the following item. So, in this case, the first color will be assigned to the cells with a value between 400 and 899. The following screenshot shows the applied color ramp: Setting a feature's color using a column in a CSV file Comma Separated Value (CSV) files are an easy way to store basic geospatial information. But you can also store styling properties alongside the geospatial data for QGIS to use in order to dynamically style the feature data. In this recipe, we'll load some points into QGIS from a CSV file and use one of the columns to determine the color of each point. Getting ready Download the sample zipped CSV file from the following URL: https://github.com/GeospatialPython/Learn/raw/master/point_colors.csv.zip Extract it and place it in your qgis_data directory in a directory named shapes. How to do it… We'll load the CSV file into QGIS as a vector layer and create a default point symbol. Then we'll specify the property and the CSV column we want to control. Finally we'll assign the symbol to the layer and add the layer to the map: First, create the URI string needed to load the CSV: uri = "file:///qgis_data/shapes/point_colors.csv?" uri += "type=csv&" uri += "xField=X&yField=Y&" uri += "spatialIndex=no&" uri += "subsetIndex=no&" uri += "watchFile=no&" uri += "crs=epsg:4326" Next, create the layer using the URI string: lyr = QgsVectorLayer(uri,"Points","delimitedtext") Now, create a default symbol for the layer's geometry type: sym = QgsSymbolV2.defaultSymbol(lyr.geometryType()) Then, we access the layer's symbol layer: symLyr = sym.symbolLayer(0) Now, we perform the key step, which is to assign a symbol layer property to a CSV column: symLyr.setDataDefinedProperty("color", '"COLOR"') Then, we change the existing symbol layer with our data-driven symbol layer: lyr.rendererV2().symbols()[0].changeSymbolLayer(0, symLyr) Finally, we add the layer to the map and verify that each point has the correct color, as defined in the CSV: QgsMapLayerRegistry.instance().addMapLayers([lyr]) How it works… In this example, we pulled feature colors from the CSV, but you could control any symbol layer property in this manner. CSV files can be a simple alternative to databases for lightweight applications or for testing key parts of a large application before investing the overhead to set up a database. Creating a complex vector layer symbol The true power of QGIS symbology lies in its ability to stack multiple symbols in order to create a single complex symbol. This ability makes it possible to create virtually any type of map symbol you can imagine. In this recipe, we'll merge two symbols to create a single symbol and begin unlocking the potential of complex symbols. Getting ready For this recipe, we will need a line shapefile, which you can download and extract from https://github.com/GeospatialPython/Learn/raw/master/paths.zip. Add this shapefile to a directory named shapes in your qgis_data directory. How to do it… Using Python Console, we will create a classic railroad line symbol by placing a series of short, rotated line markers along a regular line symbol. To do this, we need to perform the following steps: First, we load our line shapefile: lyr = QgsVectorLayer("/qgis_data/shapes/paths.shp", "Route", "ogr") Next, we get the symbol list and reference the default symbol: symbolList = lyr.rendererV2().symbols() symbol = symbolList[0] Then,we create a shorter variable name for the symbol layer registry: symLyrReg = QgsSymbolLayerV2Registry Now, we set up the line style for a simple line using a Python dictionary: lineStyle = {'width':'0.26', 'color':'0,0,0'} Then, we create an abstract symbol layer for a simple line: symLyr1Meta = symLyrReg.instance().symbolLayerMetadata("SimpleLine") We instantiate a symbol layer from the abstract layer using the line style properties: symLyr1 = symLyr1Meta.createSymbolLayer(lineStyle) Now, we add the symbol layer to the layer's symbol: symbol.appendSymbolLayer(symLyr1) Now,in order to create the rails on the railroad, we begin building a marker line style with another Python dictionary, as follows: markerStyle = {} markerStyle['width'] = '0.26' markerStyle['color'] = '0,0,0' markerStyle['interval'] = '3' markerStyle['interval_unit'] = 'MM' markerStyle['placement'] = 'interval' markerStyle['rotate'] = '1' Then, we create the marker line abstract symbol layer for the second symbol: symLyr2Meta = symLyrReg.instance().symbolLayerMetadata("MarkerLine") We instatiate the symbol layer, as shown here: symLyr2 = symLyr2Meta.createSymbolLayer(markerStyle) Now, we must work with a subsymbol that defines the markers along the marker line: sybSym = symLyr2.subSymbol() We must delete the default subsymbol: sybSym.deleteSymbolLayer(0) Now, we set up the style for our rail marker using a dictionary: railStyle = {'size':'2', 'color':'0,0,0', 'name':'line', 'angle':'0'} Now, we repeat the process of building a symbol layer and add it to the subsymbol: railMeta = symLyrReg.instance().symbolLayerMetadata("SimpleMarker") rail = railMeta.createSymbolLayer(railStyle) sybSym.appendSymbolLayer(rail) Then, we add the subsymbol to the second symbol layer: symbol.appendSymbolLayer(symLyr2) Finally, we add the layer to the map: QgsMapLayerRegistry.instance().addMapLayer(lyr) How it works… First, we must create a simple line symbol. The marker line, by itself, will render correctly, but the underlying simple line will be a randomly chosen color. We must also change the subsymbol of the marker line because the default subsymbol is a simple circle. Using an outline for font markers Font markers open up broad possibilities for icons, but a single-color shape can be hard to see across a varied map background. Recently, QGIS added the ability to place outlines around font marker symbols. In this recipe, we'll use font marker symbol methods to place an outline around the symbol to give it contrast and, therefore, visibility on any type of background. Getting ready Download the following zipped shapefile. Extract it and place it in a directory named ms in your qgis_data directory: https://github.com/GeospatialPython/Learn/raw/master/tourism_points.zip How to do it… This recipe will load a layer from a shapefile, set up a font marker symbol, put an outline on it, and then add it to the layer. We'll use a simple text character, an @ sign, as our font marker to keep things simple: First, we need to import the QtGUI library, so we can work with color objects: from PyQt4.QtGui import * Now, we create a path string to our shapefile: src = "/qgis_data/ms/tourism_points.shp" Next, we can create the layer: lyr = QgsVectorLayer(src, "Points of Interest", "ogr") Then, we can create the font marker symbol specifying the font size and color in the constructor: symLyr = QgsFontMarkerSymbolLayerV2(pointSize=16, color=QColor("cyan")) Now, we can set the font family, character, outline width, and outline color: symLyr.setFontFamily("'Arial'") symLyr.setCharacter("@") symLyr.setOutlineWidth(.5) symLyr.setOutlineColor(QColor("black")) We are now ready to assign the symbol to the layer: lyr.rendererV2().symbols()[0].changeSymbolLayer(0, symLyr) Finally, we add the layer to the map: QgsMapLayerRegistry.instance().addMapLayer(lyr) Verify that your map looks similar to the following image: How it works… We used class methods to set this symbol up, but we also could have used a property dictionary just as easily. Note that the font size and color were set in the object constructor for the font maker symbol instead of using setter methods. QgsFontMarkerSymbolLayerV2 doesn't have methods for these two properties. Using arrow symbols Line features convey location, but sometimes you also need to convey a direction along a line. QGIS recently added a symbol that does just that by turning lines into arrows. In this recipe, we'll symbolize some line features showing historical human migration routes around the world. This data requires directional arrows for us to understand it: Getting ready We will use two shapefiles in this example. One is a world boundaries shapefile and the other is a route shapefile. You can download the countries shapefile here: https://github.com/GeospatialPython/Learn/raw/master/countries.zip You can download the routes shapefile here: https://github.com/GeospatialPython/Learn/raw/master/human_migration_routes.zip Download these ZIP files and unzip the shapefiles into your qgis_data directory. How to do it… We will load the countries shapefile as a background reference layer and then, the route shapefile. Before we display the layers on the map, we'll create the arrow symbol layer, configure it, and then add it to the routes layer. Finally, we'll add the layers to the map. First, we'll create the URI strings for the paths to the two shapefiles: countries_shp = "/qgis_data/countries.shp" routes_shp = "/qgis_data/human_migration_routes.shp" Next, we'll create our countries and routes layers: countries = QgsVectorLayer(countries_shp, "Countries", "ogr") routes = QgsVectorLayer(routes_shp, "Human Migration Routes", "ogr") Now, we’ll create the arrow symbol layer: symLyr = QgsArrowSymbolLayer() Then, we’ll configure the layer. We'll use the default configuration except for two paramters--to curve the arrow and to not repeat the arrow symbol for each line segment: symLyr.setIsCurved(True) symLyr.setIsRepeated(False) Next, we add the symbol layer to the map layer: routes.rendererV2().symbols()[0].changeSymbolLayer(0, symLyr) Finally, we add the layers to the map: QgsMapLayerRegistry.instance().addMapLayers([routes,countries]) Verify that your map looks similar to the following image: How it works… The symbol calculates the arrow's direction based on the order of the feature's points. You may find that you need to edit the underlying feature data to produce the desired visual effect, especially when using curved arrows. You have limited control over the arc of the curve using the end points plus an optional third vertex. This symbol is one of the several new powerful visual effects added to QGIS, which would have normally been done in a vector illustration program after you produced a map. Summary In this article, weprogrammatically created dynamic maps using Python to control every aspect of the QGIS map canvas. We learnt to dynamically apply symbology from data in a CSV file. We also learnt how to use some newer QGIS custom symbology including font markers, arrow symbols, null symbols, and the powerful new 2.5D renderer for buildings. Wesaw that every aspect of QGIS is up for grabs with Python, to write your own application. Sometimes, the PyQGIS API may not directly support our application goal, but there is nearly always a way to accomplish what you set out to do with QGIS. Resources for Article: Further resources on this subject: Normal maps [article] Putting the Fun in Functional Python [article] Revisiting Linux Network Basics [article]
Read more
  • 0
  • 0
  • 4330

article-image-working-home-page-components-and-custom-links
Packt
10 May 2013
6 min read
Save for later

Working with Home Page Components and Custom Links

Packt
10 May 2013
6 min read
(For more resources related to this topic, see here.) Creating a Personal Setup link using the standard Custom Links on the sidebar All users need to change their personal settings, from time to time, in the Salesforce CRM application. They may, for example, wish to edit their user information, change their password, or you may need them to grant login access to administrators, plus many other reasons. Accessing the Personal Setup area is done by users clicking on their name, looking for the Setup link in the drop-down list, clicking on the Setup link, and then finally clicking on the Personal Setup link in the sidebar. All this takes time and can often be a challenge for less-experienced users of the application. By providing a direct shortcut link in the sidebar, all users will be able to access their Personal Setup area with a single click, and save their time and efforts. How to do it... Carry out the following steps to create a Personal Setup link in the sidebar: Navigate to the home page components' setup page by going to Your Name | Setup | Customize | Home | Home Page Components. Locate the Custom Links row within the Standard Components section. Click on Edit. Within the Custom Links page you can enter a maximum of 15 links. Enter Personal Setup in the 1. Bookmark field. Enter /ui/setup/Setup?setupid=PersonalSetup in the corresponding URL field, as shown in the following screenshot: Click on Save. We now need to add the standard Custom Links component to a home page layout (if it has not been already added). Navigate to the home page components setup page by going to Your Name | Setup | Customize | Home | Home Page Layouts. Determine which home page layout to place the component on and click on Edit. Here we are editing the home page layout named DE Default, as shown in the following screenshot: We will be presented with the Step 1. Select the components to show page. Check the Custom Links checkbox in the Select Narrow Components to Show section, as shown in the following screenshot: Click on Next. Move Custom Links to the top position in the Narrow (Left) Column using the Arrange the component on your home page section, as shown in the following screenshot: Click on Save. How it works... The link appears in the sidebar within the standard Custom Links section, as shown in the following screenshot: When the link is clicked, the user is immediately presented with their Personal Setup page. There's more... Clicking on the link displays the Personal Setup page in the same window and is useful when there is no requirement for the link to open up in a new browser window. The following screenshot shows the result of clicking on the Personal Setup Custom Link: See also The Using Custom Links to open Training in a new window from the sidebar recipe in this article. Using Custom Links to open Training in a new window from the sidebar In the Salesforce CRM application, there are various options for help and training. Accessing the training area is done by the users by clicking on the Help link at the top of the page (which then opens in a new browser window). Users then need to look for the Training tab within the new page and then click on the tab. All this takes a little time and can often be a challenge for less-experienced users of the application. By providing a direct shortcut link in the sidebar, all users will be able to open Training automatically in a new window with a single click, thus saving time and effort. How to do it... Carry out the following steps to create a link in the sidebar to open Training in a new window: Navigate to the Custom Links home page by going to Your Name | Setup | Customize | Home | Custom Links. Click on New. Enter the label of the Custom Link in the Label field. Here, type the text Training. Accept the default name of the Custom Link in the Name field, Training. Leave the Protected Component checkbox unchecked. The Protected Component option is used by developers to mark the Custom Link as protected in managed packages. This then allows the developer to delete the link in any future releases of the managed package without worrying about causing package installations to fail. Enter the following description in the Description field: This a link to Salesforce Training. Choose the Display in new window option from the Behavior picklist. Choose the URL option from the Content Source picklist. Enter /help/doc/user_ed.jsp?loc=training into the source section as shown in the following screenshot: Ensure the selection Unicode (UTF-8) is set in the Link Encoding picklist. Click on Save. We now need to create a custom home page component to house this custom link. The alert displayed in the following screenshot reminds us of that: Click on OK. Now navigate to the home page components setup page by going to Your Name | Setup | Customize | Home | Home Page Components. Click on New. Click on Next (on the Understanding Custom Components splash screen, if shown). The Next button is found on the Understanding Custom Components splash screen (this page is only shown if the Don't show this page again checkbox has not previously been checked) as in the following screenshot: Here, we will be presented with the Step 1. New Custom Components page. Enter the name of the Custom Component in the Name field. Enter the text Custom Links (in New Window). Select the Links option from the Type options list as shown in the following screenshot: Click on Next. Now add the Training link to the list of Custom Links to show as shown in the following screenshot: Click on Save We have created our Training link's custom home page component but we are not finished yet. We now need to add the custom home page component to a home page layout. Navigate to the home page components setup page by going to Your Name | Setup | Customize | Home | Home Page Layouts. Determine which home page layout to place the component on and click on Edit. Here we are editing the home page layout named DE Default, as shown in the following screenshot: We will be presented with the Step 1. Select the components to show page. Check the Custom Links (in New Window) checkbox in the Select Narrow Components to Show section as shown in the following screenshot: Click on Next. Move Custom Links (in New Window) to the top position in Narrow (Left) Column using the Arrange the component on your home page. section, as shown in the following screenshot: Click on Save. How it works... Clicking on the Training link opens a new smaller browser window with the Salesforce Training page directly accessed and loaded alongside the main Salesforce CRM application windows. Users can switch back to the main application when they want and simply close the Training window when they are finished viewing it. You can see what this looks like in the following screenshot: See also The Creating a Personal Setup link using the standard Custom Links on the sidebar recipe in this article.
Read more
  • 0
  • 0
  • 4320

article-image-development-ajax-web-widget
Packt
08 Oct 2009
10 min read
Save for later

Development of Ajax Web Widget

Packt
08 Oct 2009
10 min read
We’ve seen this kind of thing done by the popular bookmark sharing website, digg.com. We don’t need to visit digg.com to digg the URL. We can do it using a small object called Widget, provided by digg.com. This is just one simple example of providing remote functionality; you can find lots of widgets providing different functionality across various websites. What is a web widget? A web widget is a small piece of code provided by a third party website, which can be installed and executed in any kind of web page which is created using HTML (or XHTML). The common technologies used in web widgets are JavaScript, Ajax and Adobe flash but in some places other technologies such as HTML combined with CSS, and Java Applets are also used. A web widget can be used for: Serving useful information from a website. Providing some functionality (like: voting, polling). Endorsing the products and services of a website. Web widgets are also known as badges, modules, and snippets. And, these are commonly used by bloggers, social network users and advertisers. Popular Web Widgets You can find many examples of the web widgets on the World Wide Web. These include: Google Adsense – It is probably the most popular web widget you can see on the World Wide Web. All you’ve to do, is get a few lines of code from Google and place it in your website. Different kinds of contextual advertisements get displayed on your website according to the content displayed on your website. Digg this widget – If You want to display news or articles then you’re most probably going to do so with this widget. Provided by the social book marking website digg.com, it is one of the popular bookmark sharing websites. Your website will lots of visitors if your article gets more and more digs, and gets featured on the first page. Del.icio.us widget – You might have seen the widget previously, or text showing “Save to del.icio.us”, “Add to del.icio.us” and “saved by XXX users”. This is another popular social bookmarking website. Snap preview –Provided by snap.com, this widget shows the thumbnail preview of a web page. Survey widget from Polldaddy.com – If you need to run some kind of poll then you can use this widget to create and manage the poll on your website. Google Maps – A rather well known widget, which adds different map functionality in Google maps. you must get an api key from Google to use this widget. Benefits of Providing Web Widgets I came to know about dzone.com, a social bookmarking website for web and software developers, from a widget I found in a blog. Let’s look at the benefits of web widgets: A widget can be an excellent publicity tool. Most of the people who come to know about digg.com, del.icio.us or reddit.com do so from their web widgets in various news portal and blogs. Providing web services- This is useful since the user doesn’t have to visit that particular website to get its services. For example, a visitor to a website which has a Polldaddy web widgets can participate on a survey without visiting to polldaddy.com. Web widgets can be one of the ways of bringing income for your website, by utilizing advertising widgets such as Google adsense (discussed above). Widgets can generate more traffic to your website. For example, you can make a widget that evaluates the price of a product on a website. Widgets across multiple websites means visitors from multiple sources, hence more traffic to you website. How do Web Widgets work As can be seen in the above figure, the web widget is used by a widget client, which is a web page. The web pages just use a chunk of code provided by the functionality providing website. Furthermore, all the services and functionality are provided by the code residing on the remote server which the widget client doesn’t have to care about. In a web widget system, there is optional system called Widget Management System which can manage the output of the widget. Widget Management System A Widget Management System is used for controlling the various operations of the widget, including things like height or width or color. Most widget providing websites allows you to customize the way widget looks in blogs or website. For example, you can customize the size and color of Google adsense by logging into the Google adsense account system. Some widget Management Systems also allow you to manage the content of the widget as well. In the survey widget from vizu.com, you can manage parameters like the topic of poll and number of answers of the poll. Concept of Technologies Used To make the most out of Ajax web widgets, let’s get familiar with some technologies. HTML and XHTML Hypertext Markup language(HTML) is one of the most known markup language for constructing web pages. As the name implies, we use it to markup the text document so that web browsers know how to display them. XHTML on the other hand, is the way to standardize the HTML by making HTML a dialect of XML. XHTML comes in different flavors like transitional, strict or frameset, with each flavor offering either different capabilities or different degrees of conformance to the XML standard. Difference between HTML and XHTML The single biggest difference between HTML and XHTML is that XHML must be well-formed according to XML conventions. Because an XHTML document is essentially XML in nature, simply following the traditional HTML practices is not enough. An XHML document must be well formed. For example, let’s take the examples of “img” and “input” elements of HTML. <img src="logo.gif" alt="My Site" border="0" > <input type="text" name="only_html" id="user_name" value="Not XHTML" > Both of the above statements are perfect HTML statements but they are not well graded constructions in XHTML as they are not well formed according to compliance of XML (those tags are not enclosed properly). To figure out the difference, first look at the above tags in the XHML valid syntax. <img src="logo.gif" alt="My Site" border="0" /><input type="text" name="only_html" id="user_name" value="Not XHTML" /> Did you find the difference? The latter tags are well formed and the previous one is not. If you look closely, you can find that the HTML tags in the second example are closed like XML. The point is you should have well formed document in order to allow JavaScript to access the DOM. You can also add comments in the HTML document. Any information beginning with the character string <!-- and ending with the string --> will be ignored: <!-- This is a comment within HTML--> You can add the comment in the same fashion in an XML document as well. Concept of IFRAME IFrame (Inline Frame ) is a useful HTML element for creating web widgets. Using IFrame, we can embed the HTML document from the remote server into our document. This feature is most commonly used in the web widgets. We can define the width and height of IFrame using the height and width property of the IFrame element. IFrame can be defined in any part of the web pages. IFrame behaves like an inline object and the user can scroll through the Iframe to view the content which is out of view. We can also remove the scroll bar from the IFrame by setting scrolling property to no. The embedded document can be reloaded asynchronously using IFrame and can be an alternative option to an XMLHttpRequest object. For this reason, IFrames are widely used by Ajax applications. You can use the IFrame in the HTML document in the following way: <html> <body> <iframe src="http://wwww.example.com" width="200"> If your browser doesn’t support IFrame, this text will be displayed in the browser </iframe> </body></html> CSS(Cascading Style Sheet) A Cascading Style Sheet is a style sheet language which is used to define the presentation of document written in HTML or XHTML pages. CSS is mainly used for defining the layout, colors and fonts of the elements of a web page along with other perspectives of the document. While the mark up language can be used to define the content of the web page, the primary goal of providing a CSS is to separate the document’s content from the document’s presentation. The Internet Media type “text/css” is reserved for CSS. Using Cascading Style Sheet CSS can be used in different ways in a web page. It can be written with the <style></style> tag of the web-page. It can be defined in the style attribute of the element. Also, CSS can be defined in a different page with extension .css that links with the web page to define the presentation. What is the benefit of using CSS then? You can define the values for a set of attributes for all HTML elements (of a similar type), then change the presentation with one change in the CSS property <style type="text/css">all the css declaration goes here</style> But what about defining the CSS property for different web pages? The above method can be cumbersome and you would need to replicate the same code to different web pages. To overcome such a situation, you can define all the property in a single page let’s say call it style.css and link that CSS to the web pages. <link href="style.css" type="text/css" rel="stylesheet" /> Furthermore, you can define the styles within the elements using the style property of the HTML elements, which is commonly known as inline styles. <p style="text-align:justify">This is content inside paragraph</p> As you’ve seen, we’ve quickly defined the text-align attribute to justify Defining Style Sheet rules A style sheet allows you to change the different attributes of the HTML elements by defining a styling rule for them. A rule has two components: selectors, which defines which HTML elements to apply the styling rule and declaration, which contains the styling rule for the selectors. p { background-color:#999999 } In the above css rule, p is the selector and background-color:#999999, is the declaration of the rule. The above style defines the rule for the paragraph element <p></p>. .box { width:300px } In the above rule, selectors is defined as a class and it can be used in any element with the class property of the element. <p class="box">..content..</p> <div class="box">content</div> Class can be used with any HTML element. #container { width:1000px } “#” is known as an id selector in CSS. The above rule applies to an element which has the id “container” such as below: <div id="container">..content..</div> We can also define a set of rules for multiple elements using comma (,) among the selectors: h1, h2, h3 {font-size:12px; color:#FF0000 } There are many more styles of defining selectors and CSS properties.
Read more
  • 0
  • 0
  • 4320

article-image-build-your-own-application-access-twitter-using-java-and-netbeans-part-2
Packt
19 Feb 2010
17 min read
Save for later

Build your own Application to access Twitter using Java and NetBeans: Part 2

Packt
19 Feb 2010
17 min read
In this tutorial, we’ll develop the simple Java application further to add some more functions. Now that we can connect to our Twitter account via the Twitter4J API, it would be nice to use a login dialog instead of hard-coding our Twitter username and password in the Java application. But before we start to build our enhanced SwingAndTweet application, let me show you how it will look like once we finish all the exercises in this part of the tutorial: And now, let the show begin… Creating a Login dialog for our SwingAndTweet application Open your NetBeans IDE along with your SwingAndTweet project, and make sure you’re in the Design View. Go to the Palette window and locate the Dialog component under the Swing Windows section; then drag and drop it anywhere inside the SwingAndTweetUI JFrame component: A JDialog will be added automatically to your SwingAndTweet application, and it will show up in the Component Inspector tab located at the lower-left part of the screen, under Other Components: Right-click on the jDialog1 component in the Inspector tab and select Change Variable Name… from the pop-up menu. The Rename dialog will show up next. Type twitterLogin in the New Name field and press Enter to change the dialog’s name. Now you can start adding text fields, labels and buttons to your twitterLogin dialog. Double-click on the twitterLogin component under the Inspector tab. The twitterLogin dialog will show up empty in the Design Editor window. Use the Palette window to add two JLabels, one JTextField, one JPasswordField and two JButtons to the twitterLogin dialog. Arrange these controls as shown below: Now let’s change the names of the JTextField control, the JPasswordField control and the two JButton controls, so we can easily identify them within your SwingAndTweet application’s code. Right-click on the first text field (jLabel2), select Change Variable Name… from the pop-up menu and replace the text field’s name with txtUsername. Do the same with the other fields; use txtPassword for the JPasswordField control, btnLogin for the Login button and btnExit for the Exit button. And now the last touch. Right-click anywhere inside the twitterLogin dialog, being careful not to right-click inside any of the controls, and select the Properties option from the pop-up menu. The twitterLogin [JDialog] – Properties dialog will appear next. Locate the title property, double-click on the null value and type Twitter Login to replace it. Next, scroll down the properties list until you find the modal property; click on its checkbox to enable it and then click on Close to save your changes. Basically, in the previous exercise we added all the Swing controls you’re going to need to type your username and password, so you can connect to your Twitter account. The twitterLogin dialog is going to take care of the login process for your SwingAndTweet application. We replaced the default names for the JTextField, the JPasswordField and the two JButton controls because it will be easier to identify them during the coding process of the application. On step 8 we used the Properties window of the twitterLogin dialog to change the title property and give your dialog a decent title. We also enabled the modal property on step 9, so you can’t just close the dialog and jump right to the SwingAndTweetUI main window; you’ll have to enter a valid Twitter username and password combination for that. Invoking the Login dialog Ok, now we have a good-looking dialog called twitterLogin. The next step is to invoke it before our main SwingAndTweet JFrame component shows up, so we need to insert some code inside the SwingAndTweetUI() constructor method. Click on the Source button of the Editor window to change to the Source View: Now locate the SwingAndTweetUI() constructor, and type the following lines right after the initComponents(); line: int loginWidth = twitterLogin.getPreferredSize().width; int loginHeight = twitterLogin.getPreferredSize().height; twitterLogin.setBounds(0,0,loginWidth,loginHeight); twitterLogin.setVisible(true); The code inside the SwingAndTweetUI() constructor method shall now look like this: To see your new twitterLogin dialog in action, press F6 or select Run | Run Project to run your SwingAndTweetUI application. The twitterLogin dialog will pop right up. You’ll be able to type in your username and password, but since we haven’t added any functionality yet, the buttons won’t do anything right now. Click on the Close (X) button to close the dialog window and the SwingAndTweetUI main window will appear next. Click on its Close (X) button to exit your Twitter Java application. Now let’s take a look at the code we added to your twitterLogin dialog. On the first line, int loginWidth = twitterLogin.getPreferredSize().width; we declare an integer variable named loginWidth, and assign to it the preferred width of the twitterLogin dialog. The getPreferredSize method retrieves the value of the preferredSize property from the twitterLogin dialog through the .width field. On the second line, int loginHeight = twitterLogin.getPreferredSize().height; we declare another integer variable named loginHeight, and assign to it the preferred height of the twitterLogin dialog. This time, the getPreferredSize() method retrieves the value of the preferredWidth property from the twitterLogin dialog through the .height field. On the next line, twitterLogin.setBounds(0,0,loginWidth,loginHeight); we use the setBounds method to set the x,y coordinates where the dialog should appear on the screen, along with its corresponding width and height. The first two parameters are for the x,y coordinates; in this case, x=0 and y=0, which means the twitterLogin dialog will show up at the upper-left part of the screen. The last two parameters receive the value of the loginWidth and loginHeight variables to establish the twitterLogin dialog’s width and height, respectively. The last line, twitterLogin.setVisible(true); makes the twitterLogin dialog appear on the screen. And since the modal property of this dialog is enabled, once it shows up on the screen it won’t let you do anything else with your SwingAndTweet1 application until you close it up or enter a valid Twitter username and password, as we’ll see in the next exercise. Adding functionality to the twitterLogin dialog Now your twitterLogin dialog is ready to roll! Basically, it won’t let you go to the SwingAndTweet main window until you’ve entered a valid Twitter username and password. And for doing that, we’re going to use the same login code from Build your own Application to access Twitter using Java and NetBeans: Part 1 of this article series. Go to the end of your SwingAndTweetUI application source code and locate the // Variables declaration – do not modify line. Below this line, you’ll see all the variables used in your application: the btnExit and btnLogin buttons, the text fields from your twitterLogin dialog and your SwingAndTweetUI main window, etc. Add the following line just below the // End of variables declaration line:     Twitter twitter; Now click on the Design button to change to the Design View: You’ll see the twitterLogin dialog again –in case you don’t, double-click on the twitterLogin component under the Inspector tab. Now double-click on the Login button to go back to the Code View. The btnLoginActionPerformed method will show up next. Add the following code inside this method: try { twitter = new Twitter(txtUsername.getText(), String.valueOf(txtPassword.getPassword())); twitter.verifyCredentials(); JOptionPane.showMessageDialog(null, "You're logged in!"); twitterLogin.dispose(); } catch (TwitterException e) { JOptionPane.showMessageDialog (null, "Login failed"); } Make sure you write each line on its own, to avoid errors. The btnLoginActionPerformed method shall look like this: Now you’re ready to test your twitterLogin dialog. Press F6 to run your application. The Twitter Login dialog will show up next. Type your Twitter username and password, and then click on the OK button. If the username and password are correct, the You’re logged in! dialog will show up and you’ll be able to go to the SwingAndTweetUI main window. If they’re not correct, the Login failed dialog will appear instead and, after you click on the OK button, you’ll return to the twitterLogin dialog until you type a correct Twitter username and password combination. To exit your SwingAndTweetUI application, click on the Close(X) button of the twitterLogin dialog and then on the Close(X) button of the SwingAndTweetUI window. You’ll be taken back to the NetBeans IDE. Click on the Design button to go back to the Design View, and double-click on the Exit button to open the btnExitActionPerformed method. Type System.exit(0); inside the btnExitActionPerformed method, as shown below: Now go back to the Design View again, right-click anywhere inside the twitterLogin dialog (just be careful not to right-click over any of the dialog’s controls) and select the Events | Window | windowClosing option from the pop-up menu: NetBeans will change to Code View automatically and you’ll be inside the twitterLoginWindowClosing method. Type System.exit(0); inside this method, as shown below: Now run your application to test the new functionality in your loginTwitter dialog. You’ll be able to exit the SwingAndTweet application when clicking on the Exit or Close(X) buttons, and you’ll be able to go to your application’s main window if you type a correct Twitter username and password combination. You can close your SwingAndTweet application now. And now, let’s examine what we just accomplished. First you added the Twitter twitter; line to your application code. With this line we’re declaring a Twitter object named twitter, and it will be available throughout all the application code. On step 4, you added some lines of code to the btnLoginActionPerformed method; this code will be executed every time you click on the Login button from the twitterLogin dialog. All the code is enclosed in a try block, so that if an error occurs during the login process, a TwitterException will be thrown and the code inside the catch block will execute. The first line inside the try block is twitter = new Twitter(txtUsername.getText(),String.valueOf(txtPassword.getPassword())); This code creates the twitter object that we’re going to use throughout the application. It uses the text value you entered in the txtUsername and txtPassword fields to log into your Twitter account. The next line, twitter.verifyCredentials(); checks to see if the username and password provided to the twitter object are correct; if that’s true, a message dialog box shows up in the screen with the You’re logged in! message and the rest of the code executes once you click on the OK button of this message dialog; otherwise, the code in the catch block executes and a message dialog shows up in the screen with the Login failed message, and the twitterLogin dialog keeps waiting for you to type a correct username and password combination. The next line in the sequence, JOptionPane.showMessageDialog(null, "You're logged in!"); shows the message dialog that we talked about before, and the last line inside the try block, twitterLogin.dispose(); makes the twitterLogin dialog disappear from the screen once you’ve logged into your Twitter account successfully. The only line of code inside the catch block is JOptionPane.showMessageDialog (null, "Login failed"); This line executes when there’s an error in the Twitter login process; it shows the Login failed message in the screen and waits for you to press the OK button. On step 9 we added one line of code to the btnExitActionPerformed method: System.exit(0); This line closes your SwingAndTweet application whenever you click on the Exit button. Finally, on steps 10-12 we added another System.exit(0); line to the twitterLoginWindowClosing method, to close your SwingAndTweet application whenever you click on the Close(X) button of the twitterLogin dialog. Showing your Twitter timeline right after logging in Now let’s see some real Twitter action! The following exercise will show you how to show your most recent tweets inside a text area. Click on the Design button to go to the Design View; then double-click on the [JFrame] component under the Inspector tab to show the SwingAndTweetUI dialog in the Design View window: The SwingAndTweet frame will show the three controls we created during Build your own Application to access Twitter using Java and NetBeans: Part 1. Replace the My Last Tweet text in the JLabel control with the What’s happening text. Then right-click on the JTextField control and select the Change Variable Name… option from the pop-up menu, to change its name from jTextField1 to txtUpdateStatus. Now do the same with the JButton control. Right-click on it and select the Change Variable Name… option from the pop-up menu to change its name from jButton1 to btnUpdateStatus. Right-click on the same button again, but this time select the Edit Text option from the pop-up menu and replace the Login text with Update. Rearrange the three controls as per the following screenshot (you’ll need to make the SwingAndTweet container wider): Now drag a JTextArea control from the Palette window and drop it inside the SwingAndTweetUI container. Resize the text area so it fills up the rest of the container, as shown below: Double-click on the Update button to open the btnUpdateStatusActionPerformed method. The first thing you’ll notice is that it’s not empty; this is because this used to be the old Login button, remember? Now just replace all the code inside this method, as shown below: private void btnUpdateStatusActionPerformed(java.awt.event.ActionEvent evt) { try { if (txtUpdateStatus.getText().isEmpty()) JOptionPane.showMessageDialog (null, "You must write something!"); else { twitter.updateStatus(txtUpdateStatus.getText()); jTextArea1.setText(null); java.util.List<Status> statusList = twitter.getUserTimeline(); for (int i=0; i<statusList.size(); i++) { jTextArea1.append(String.valueOf(statusList.get(i).getText())+"n"); jTextArea1.append("-----------------------------n"); } } } catch (TwitterException e) { JOptionPane.showMessageDialog (null, "A Twitter Error ocurred!"); } txtUpdateStatus.setText(""); jTextArea1.updateUI(); The next step is to modify your btnLoginActionPerformed method; we need to add several lines of code to show your Twitter timeline. The complete method is shown below (the lines you need to add are shown in bold): private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) { try { twitter = new Twitter(txtUsername.getText(), String.valueOf(txtPassword.getPassword())); twitter.verifyCredentials(); // JOptionPane.showMessageDialog(null, "You're logged in!"); java.util.List<Status> statusList = twitter.getUserTimeline(); for (int i=0; i<statusList.size(); i++) { jTextArea1.append(String.valueOf(statusList.get(i).getText())+"n"); jTextArea1.append("-----------------------------n"); } twitterLogin.dispose(); } catch (TwitterException e) { JOptionPane.showMessageDialog (null, "Login failed"); } jTextArea1.updateUI(); } Once you have added all the necessary code in each button’s actionPerformed method, press F6 to run the SwingAndTweet application and check if all things work as intended. If you type a message in the txtUpdateStatus text field and then click on the Update button, the timeline information inside the JTextArea1 control will change to reflect your new Twitter status: You can close your SwingAndTweet application now. That was cool, right? Now you have a much better-looking Twitter client! And you can update your status, too! Let’s examine the code we added in this last exercise… private void btnUpdateStatusActionPerformed(java.awt.event.ActionEvent evt) { try { if (txtUpdateStatus.getText().isEmpty()) JOptionPane.showMessageDialog (null, "You must write something!"); else { twitter.updateStatus(txtUpdateStatus.getText()); jTextArea1.setText(null); java.util.List<Status> statusList = twitter.getUserTimeline(); for (int i=0; i<statusList.size(); i++) { jTextArea1.append(String.valueOf(statusList.get(i).getText())+"n"); jTextArea1.append("-----------------------------n"); } } } catch (TwitterException e) { JOptionPane.showMessageDialog (null, "A Twitter Error ocurred!"); } txtUpdateStatus.setText(""); jTextArea1.updateUI(); On step 7 we added some code to the btnUpdateStatusActionPerformed method. This code will execute whenever you click on the Update button to update your Twitter status. First, let’s look at the code inside the try block. The first two lines, if (txtUpdateStatus.getText().isEmpty()) JOptionPane.showMessageDialog (null, "You must write something!"); are the first part of a simple if-else statement that checks to see if you’ve written something inside the txtUpdateStatus text field; if it’s empty, a message dialog will show the You must write something! message on the screen, and then it will wait for you to click on the OK button. If the txtUpdateStatus text field is not empty, the code inside the else block will execute instead of showing up the message dialog. The next part of the code is the else block. The first line inside this block, twitter.updateStatus(txtUpdateStatus.getText()); updates your twitter status with the text you wrote in the txtUpdateStatus text field; if an error occurs at this point, a TwitterException is thrown and the program execution will jump to the catch block. If your Twitter status was updated correctly, the next line to execute is jTextArea1.setText(null); This line erases all the information inside the jTextArea1 control. And the next line, java.util.List<Status> statusList = twitter.getUserTimeline(); gets the 20 most recent tweets from your timeline and assigns them to the statusList variable. The next line is the beginning of a for statement: for (int i=0; i<statusList.size(); i++) { Basically, what this for block does is iterate through all the 20 most recent tweets in your timeline, one at a time, executing the two statements inside this block on each iteration: jTextArea1.append(String.valueOf(statusList.get(i).getText())+"n"); jTextArea1.append("-----------------------------n"); Although the getUserTimeline() function retrieves the 20 most recent tweets, we need to use the statusList.size() statement as the loop continuation condition inside the for block to get the real number of tweets obtained, because they can be less than 20, and we can’t iterate through something that maybe doesn’t exist, right? The first line appends the text of each individual tweet to the jTextArea1 control, along with a new-line character ("n") so each tweet is shown in one individual line, and the second line appends the "-----------------------------n" text as a separator between each individual tweet, along with a new-line character. The final result is a list of the 20 most recent tweets inside the jTextArea1 control. The only line of code inside the catch block displays the A Twitter Error occurred! message in case something goes wrong when trying to update your Twitter status. The next line of code right after the catch block is txtUpdateStatus.setText(""); This line just clears the content inside the txtUpdateStatus control, so you don’t accidentally insert the same message two times in a row. And finally, the last line of code in the btnUpdateStatusActionPerformed method is jTextArea1.updateUI(); This line updates the jTextArea1 control, so you can see the list of your 20 most recent tweets after updating your status. private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) { try { twitter = new Twitter(txtUsername.getText(), String.valueOf(txtPassword.getPassword())); twitter.verifyCredentials(); // JOptionPane.showMessageDialog(null, "You're logged in!"); java.util.List<Status> statusList = twitter.getUserTimeline(); for (int i=0; i<statusList.size(); i++) { jTextArea1.append(String.valueOf(statusList.get(i).getText())+"n"); jTextArea1.append("-----------------------------n"); } twitterLogin.dispose(); } catch (TwitterException e) { JOptionPane.showMessageDialog (null, "Login failed"); } jTextArea1.updateUI(); And now let’s have a look at the code we added inside the btnLoginActionPerformed method. The first thing you’ll notice is that we’ve added the '//' characters to the // JOptionPane.showMessageDialog(null, "You're logged in!"); line; this means it’s commented out and it won’t be executed, because it’s safe to go directly to the SwingAndTweet main window right after typing your Twitter username and password. The next lines are identical to the ones inside the btnUpdateStatusActionPerformed method we saw before; the first line retrieves your 20 most recent tweets, and the for block displays the list of tweets inside the jTextArea1 control.  And the last line of code, jTextArea1.updateUI(); updates the jTextArea1 control so you can see the most recent information regarding your latest tweets. Summary Well, now your SwingAndTweet application looks better, don’t you think so? In this article, we enhanced the SwingAndTweet application which we build in the first part of the tutorials series. In short, we: Created a twitterLogin dialog to take care of the login process Added functionality to show your 20 most recent tweets right after logging in Added the functionality to update your Twitter status
Read more
  • 0
  • 0
  • 4291

article-image-basics-classes-and-objects
Packt
06 Oct 2016
11 min read
Save for later

Basics of Classes and Objects

Packt
06 Oct 2016
11 min read
In this article by Steven Lott, the author of the book Modern Python Cookbook, we will see how to use a class to encapsulate data plus processing. (For more resources related to this topic, see here.) Introduction The point of computing is to process data. Even when building something like an interactive game, the game state and the player's actions are the data, the processing computes the next game state and the display update. The data plus processing is ubiquitous. Some games can have a relatively complex internal state. When we think of console games with multiple players and complex graphics, there are complex, real-time state changes. On the other hand, when we think of a very simple casino game like Craps, the game state is very simple. There may be no point established, or one of the numbers 4, 5, 6, 8, 9, 10 may be the established point. The transitions are relatively simple, and are often denoted by moving markers and chips around on the casino table. The data includes the current state, player actions, and rolls of the dice. The processing is the rules of the game. A game like Blackjack has a somewhat more complex internal state change as each card is accepted. In games where the hands can be split, the state of play can become quite complex. The data includes the current game state, the player's commands, and the cards drawn from the deck. Processing is defined by the rules of the game as modified by any house rules. In the case of Craps, the player may place bets. Interestingly, the player's input, has no effect on the game state. The internal state of the game object is determined entirely by the next throw of the dice. This leads to a class design that's relatively easy to visualize. Using a class to encapsulate data plus processing The essential idea of computing is to process data. This is exemplified when we write functions that process data. Often, we'd like to have a number of closely related functions that work with a common data structure. This concept is the heart of object-oriented programming. A class definition will contain a number of methods that will control the internal state of an object. The unifying concept behind a class definition is often captured as a summary of the responsibilities allocated to the class. How can we do this effectively? What's a good way to design a class? Getting Ready Let's look at a simple, stateful object—a pair of dice. The context for this would be an application which simulates the casino game of Craps. The goal is to use simulation of results to help invent a better playing strategy. This will save us from losing real money while we try to beat the house edge. There's an important distinction between the class definition and an instance of the class, called an object. We call this idea – as a whole – Object-Oriented Programming. Our focus is on writing class definitions. Our overall application will create instances of the classes. The behavior that emerges from the collaboration of the instances is the overall goal of the design process. Most of the design effort is on class definitions. Because of this, the name object-oriented programming can be misleading. The idea of emergent behavior is an essential ingredient in object-oriented programming. We don't specify every behavior of a program. Instead, we decompose the program into objects, define the object's state and behavior via the object's classes. The programming decomposes into class definitions based on their responsibilities and collaborations. An object should be viewed as a thing—a noun. The behavior of the class should be viewed as verbs. This gives us a hint as to how we can proceed with design classes that work effectively. Object-oriented design is often easiest to understand when it relates to tangible real-world things. It's often easier to write a software to simulate a playing card than to create a software that implements an Abstract Data Type (ADT). For this example, we'll simulate the rolling of die. For some games – like the casino game of Craps – two dice are used. We'll define a class which models the pair of dice. To be sure that the example is tangible, we'll model the pair of dice in the context of simulating a casino game. How to do it... Write down simple sentences that describe what an instance of the class does. We can call these as the problem statements. It's essential to focus on short sentences, and emphasize the nouns and verbs. The game of Craps has two standard dice. Each die has six faces with point values from 1 to 6. Dice are rolled by a player. The total of the dice changes the state of the craps game. However, those rules are separate from the dice. If the two dice match, the number was rolled the hard way. If the two dice do not match, the number was easy. Some bets depend on this hard vs easy distinction. Identify all of the nouns in the sentences. Nouns may identify different classes of objects. These are collaborators. Examples include player and game. Nouns may also identify attributes of objects in questions. Examples include face and point value. Identify all the verbs in the sentences. Verbs are generally methods of the class in question. Examples include rolled and match. Sometimes, they are methods of other classes. Examples include change the state, which applies to the Craps game. Identify any adjectives. Adjectives are words or phrases which clarify a noun. In many cases, some adjectives will clearly be properties of an object. In other cases, the adjectives will describe relationships among objects. In our example, a phrase like the total of the dice is an example of a prepositional phrase taking the role of an adjective. The the total of phrase modifies the noun the dice. The total is a property of the pair of dice. Start writing the class with the class statement. class Dice: Initialize the object's attributes in the __init__ method. def __init__(self): self.faces = None We'll model the internal state of the dice with the self.faces attribute. The self variable is required to be sure that we're referencing an attribute of a given instance of a class. The object is identified by the value of the instance variable, self We could put some other properties here as well. The alternative is to implement the properties as separate methods. These details of the design decision is the subject for using properties for lazy attributes. Define the object's methods based on the various verbs. In our case, we have several methods that must be defined. Here's how we can implement dice are rolled by a player. def roll(self): self.faces = (random.randint(1,6), random.randint(1,6)) We've updated the internal state of the dice by setting the self.faces attribute. Again, the self variable is essential for identifying the object to be updated. Note that this method mutates the internal state of the object. We've elected to not return a value. This makes our approach somewhat like the approach of Python's built-in collection classes. Any method which mutates the object does not return a value. This method helps implement the total of the dice changes the state of the Craps game. The game is a separate object, but this method provides a total that fits the sentence. def total(self): return sum(self.faces) These two methods help answer the hard way and easy way questions. def hardway(self): return self.faces[0] == self.faces[1] def easyway(self): return self.faces[0] != self.faces[1] It's rare in a casino game to have a rule that has a simple logical inverse. It's more common to have a rare third alternative that has a remarkably bad payoff rule. In this case, we could have defined easy way as return not self.hardway(). Here's an example of using the class. First, we'll seed the random number generator with a fixed value, so that we can get a fixed sequence of results. This is a way to create a unit test for this class. >>> import random >>> random.seed(1)   We'll create a Dice object, d1. We can then set its state with the roll() method. We'll then look at the total() method to see what was rolled. We'll examine the state by looking at the faces attribute. >>> from ch06_r01 import Dice >>> d1 = Dice() >>> d1.roll() >>> d1.total() 7 >>> d1.faces (2, 5)   We'll create a second Dice object, d2. We can then set its state with the roll() method. We'll look at the result of the total() method, as well as the hardway() method. We'll examine the state by looking at the faces attribute. >>> d2 = Dice() >>> d2.roll() >>> d2.total() 4 >>> d2.hardway() False >>> d2.faces (1, 3)   Since the two objects are independent instances of the Dice class, a change to d2 has no effect on d1. >>> d1.total() 7   How it works... The core idea here is to use ordinary rules of grammar – nouns, verbs, and adjectives – as a way to identify basic features of a class. Noun represents things. A good descriptive sentence should focus on tangible, real-world things more than ideas or abstractions. In our example, dice are real things. We try to avoid using abstract terms like randomizers or event generators. It's easier to describe the tangible features of real things, and then locate an abstract implementation that offers some of the tangible features. The idea of rolling the dice is an example of physical action that we can model with a method definition. Clearly, this action changes the state of the object. In rare cases – one time in 36 – the next state will happen to match the previous state. Adjectives often hold the potential for confusion. There are several cases such as: Some adjectives like first, last, least, most, next, previous, and so on will have a simple interpretation. These can have a lazy implementation as a method or an eager implementation as an attribute value. Some adjectives are more complex phrase like "the total of the dice". This is an adjective phrase built from a noun (total) and a preposition (of). This, too, can be seen as a method or an attribute. Some adjectives involve nouns that appear elsewhere in our software. We might have had a phrase like "the state of the Craps game" is a phrase where "state of" modifies another object, the "Craps game". This is clearly only tangentially related to the dice themselves. This may reflect a relationship between "dice" and "game". We might add a sentence to the problem statement like "The dice are part of the game". This can help clarify the presence of a relationship between game and dice. Prepositional phrases like "are part of" can always be reversed to create the a statement from the other object's point of view—"The game contains dice". This can help clarify the relationships among objects. In Python, the attributes of an object are – by default – dynamic. We don't specific a fixed list of attributes. We can initialize some (or all) of the attributes in the __init__() method of a class definition. Since attributes aren't static, we have considerable flexibility in our design. There's more... Capturing the essential internal state, and methods that cause state change is the first step in good class design. We can summarize some helpful design principles using the acronym SOLID. Single Responsibility Principle: A class should have one clearly-defined responsibility. Open/Closed Principle: A class should be open to extension – generally via inheritance – but closed to modification. We should design our classes so that we don't need to tweak the code to add or change features. Liskov Substitution Principle: We need to design inheritance so that a subclass can be used in place of the superclass. Interface Segregation Principle: When writing a problem statement, we want to be sure that collaborating classes have as few dependencies as possible. In many cases, this principle will lead us to decompose large problems into many small class definitions. Dependency Inversion Principle: It's less than ideal for a class to depend directly on other classes. It's better if a class depends on an abstraction, and a concrete implementation class is substituted for the abstract class. The goal is to create classes that have the proper behavior and also adhere to the design principles. Resources for Article: Further resources on this subject: Python Data Structures [article] Web scraping with Python (Part 2) [article] How is Python code organized [article]
Read more
  • 0
  • 0
  • 4277

article-image-part-2-deploying-multiple-applications-capistrano-single-project
Rodrigo Rosenfeld
01 Jul 2014
8 min read
Save for later

Part 2: Deploying Multiple Applications with Capistrano from a Single Project

Rodrigo Rosenfeld
01 Jul 2014
8 min read
In part 1, we covered Capistrano and why you would use it. We also covered mixins, which provide the base for what we will do in this post, which is to deploy a sample project using Capistrano. For this project, suppose our user interface is a combination of two applications,app1 and app2. They should be deployed to servers do and ec2. And we'll provide two environments,production and cert. Make sure Ruby and Bundler are installed before you start. First, we create a new directory for our project, and add a Gemfile to it with capistrano as a dependency. Then we will create the Capistrano directory structure: mkdircapsample cd capsample bundle init echo "gem 'capistrano'" >>Gemfile bundle bundle exec cap install STAGES="do_prod_app1,do_prod_app2,do_cert_app1,do_cert_app2,ec2_prod_app1,ec2_prod_app2,ec2_cert_app1,ec2_cert_app2" This will create nine files under config/deploy, one for each server/environment/application group. This is just to demonstrate the idea. We'll completely override their entire content later on. It will also create a Capfile file that works in a similar way to a regular Rakefile. With Rake, you can get a list of the available tasks with rake -T. With Capistrano you can get the same using: bundle exec cap -T Behind the scenes, cap is a binary distributed with the capistrano gem that will run Rake with Capfile set as the Rakefile and supporting a few other options like --roles.Now create a new file,lib/mixin.rb, with the content mentioned in the Using mixins section in part 1. Then add this to the top of the Capfile: $: . unshiftFile.dirname(__FILE__) require'lib/mixin' Each of the files under config/deploy will look very similar to each other. For instance, ec2_prod_app1 would look like this: mixin 'servers/ec2' mixin'environments/production' mixin'applications/app1' Then config/mixins/servers/ec2.rb would look like this: server 'ec2.mydomain.com', roles: [:main] set :database_host, 'ec2-db.mydomain.com' This file contains definitions that are valid (or default) for the whole server, no matter what environment or application we're deploying. In this example the database host is shared for all applications and environments hosted on our ec2 server. Something to note here is that we're adding a single role named main to our server. If we specified all roles, like [:web, :db, :assets, :puma], then they would be shared with all recipes relying on this server mixin. So, a better approach would be to add them on the application's recipe, if required. For instance, you might want to add something like set :server_name, 'ec2.mydomain.com' to your server definitions. Then you can dynamically set the role in the application's recipe by calling role :db, [fetch(:server_name)] and so on for all required roles. However, this is usually not necessary for third-party recipes as they let you decide which role the recipe should act on. For example, if you want to deploy your application with Puma you can write set :puma_role, :main. Before we discuss a full example for the application recipe, let's look at what config/mixins/environments/production.rb might look like: set :branch, 'production' set :encoding_key, '098f6bcd4621d373cade4e832627b4f6' set :database_name, 'app_production' set :app1_port, 3000 set :app2_port, 3001 set :redis_port, 6379 set :solr_port, 8080 In this example, we're assuming that the ports for app1 and app2 , Redis and Solr will be the same for production in all servers, as well as the database name. Finally, the recipes themselves, which tell Capistrano how to set up an application, will be defined byconfig/mixins/applications/app1.rb. Here's an example for a simple Rails application: Rake :: Task['load:defaults'].invoke Rake::Task['load:defaults'].clear require'capistrano/rails' require'capistrano/puma' Rake::Task['load:defaults'].reenable Rake::Task['load:defaults'].invoke set :application, 'app1' set :repo_url, 'git@example.com:me/app1.git' set :rails_env, 'production' set :assets_roles, :main set :migration_role, :main set :puma_role, :main set :puma_bind, "tcp://0.0.0.0:#{fetch :app1_port}" namespace :railsdo desc'Generate settings file' task :generate_settingsdo on roles(:all) do template ="config/templates/database.yml.erb" dbconfig=StringIO.new(ERB.new(File.read template).result binding) upload! dbconfig, release_path.join('config', 'database.yml') end end end before 'deploy:migrate', 'rails:generate_settings' # Create directories expected by Puma default settings: before 'puma:restart', 'create_log_and_tmp'do on roles(:all) do within shared_pathdo execute :mkdir, '-p', 'log', 'tmp/pids' end end end Make sure you remove the lines that set application and repo_url on the config/deploy.rb file generated bycap install. Also, if you're deploying a Rails application using this recipe you should also add the capistrano-rails andcapistrano3-puma gems to your Gemfile and run bundle again. In case you're running rbenv or rvmto install Ruby in the server, make sure you include either capistrano-rbenv or capistrano-rvm gems and require them on the recipe. You may also need to provide more information in this case. For rbenv you'd need to tell it which version to use with set :rbenv_ruby, '2.1.2' for example. Sometimes you'll find out that some settings are valid for all applications under all environments in all servers. The most important one to notice is the location for our applications as they must not conflict with each other. Another setting that could be shared across all combinations could be the private key used to connect to all servers. For such cases, you should add those settings directly to config/deploy.rb: set :deploy_to, -> { "/home/vagrant/apps/#{fetch :environment}/#{fetch :application}" } set :ssh_options, { keys: %w(~/.vagrant.d/insecure_private_key) } I strongly recommend connecting to your servers with a regular account rather than root. For our applications we use userbenv to manage our Ruby versions, so we're able to deploy them as regular users as long as our applications listen to high port numbers. We'd then setup our proxy server (nginx in our case) to forward the requests on port 80 and 443 to each application's port accordingly to the requested domains and paths. This is set up by some Chef recipes. Those recipes run as root in our servers. To connect using another user, just pass it in the server declaration. To connect to vagrant@192.168.33.10, this is how you'd set it up: server '192.168.33.10', user: 'vagrant', roles: [:main] set :ssh_options, { keys: %w(~/.vagrant.d/insecure_private_key) } Finally, we create a config/database.yml that's suited for our environment on demand, before running the migrations task. Here's what the template config/templates/database.ymlcould look like: production: adapter: postgresql encoding: unicode pool: 30 database: <%= fetch :database_name %> host: <%= fetch :database_host %> I've omitted the settings for app2 , but in case it was another Rails application, we could extract the common logic between them to another common_rails mixin. Also notice that because we're not requiring capistrano/rails and capistrano/puma in the Capfile, their default values won't be set as Capistrano has already invoked the load:defaults task before our mixins are loaded. That's why we clear that task, require the recipes, and then re-enable and re-run the task so that the default for those recipes have the opportunity to load. Another approach is to require those recipes directly in the Capfile. But unless the recipes are carefully crafted to only run their commands for very specific roles, it's likely that you can get unexpected behavior if you deploy an application with Rails, another one with Grails, and yet another with NodeJS. If any of them has commands that run for all roles, or if the role names between them conflict somehow you'd be in trouble. So, unless you have total control and understanding about all your third-party recipes, I'd recommend that you use the approach outlined in the examples above. Conclusion All the techniques presented here are used to manage our real complex scenario at e-Core, where we support multiple applications in lots of environments that are replicated in three servers. We found that this allowed us to quickly add new environments or servers as needed to recreate our application in no time. Also, I'd like to thank Juan Ibiapina, who worked with me on all these recipes to ensure our deployment procedures are fully automated—almost. We still manage our databases and documents manually because we prefer to. About the author Rodrigo Rosenfeld Rosas lives in Vitória-ES, Brazil, with his lovely wife and daughter. He graduated in Electrical Engineering with a Master’s degree in Robotics and Real-time Systems. For the past five years Rodrigo has focused on building and maintaining single page web applications. He is the author of some gems includingactive_record_migrations,rails-web-console, the JS specs runner oojspec, sequel-devise, and the Linux X11 utility ktrayshortcut. Rodrigo was hired by e-Core (Porto Alegre-RS, Brazil) to work from home, building and maintaining software for Matterhorn Transactions Inc. with a team of great developers. Matterhorn's main product, the Market Tracker, is used by LexisNexis clients .
Read more
  • 0
  • 0
  • 4276
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-building-ui-xaml-windows-8-using-c
Packt
16 Aug 2013
35 min read
Save for later

Building UI with XAML for Windows 8 Using C

Packt
16 Aug 2013
35 min read
(For more resources related to this topic, see here.) XAML C++ Store applications typically use eXtensible Application Markup Language (XAML) as the main language for creating the user interface. The first question that comes to mind when XAML is first mentioned, is why? What's wrong with C++, or any other existing programming language? XAML is an XML-based language that describes the what, not the how; it's declarative and neutral. Technically, a complete app can be written without any XAML; there's nothing XAML can do that C++ can't. Here are some reasons why XAML makes sense (or at least may make sense in a little bit): C++ is very verbose as opposed to XAML. XAML is usually shorter than the equivalent C++ code. Since XAML is neutral, design-oriented tools can read and manipulate it. Microsoft provides the Expression Blend tool just for this purpose. The declarative nature of XAML makes it easier (most of the time, after users get used to it) to build user interfaces, as these have a tree-like structure, just like XML. XAML itself has nothing to do with the user interface in itself. XAML is a way to create objects (usually an object tree) and set their properties. This works for any type that is "XAML friendly", meaning it should have the following: A default public constructor Settable public properties The second point is not a strict requirement, but without properties the object is pretty dull. XAML was originally created for Windows Presentation Foundation (WPF), the main rich client technology in .NET. It's now leveraged in other technologies, mostly in the .NET space, such as Silverlight and Windows Workflow Foundation (WF). The XAML level currently implemented in WinRT is roughly equivalent to Silverlight 3 XAML. In particular, it's not as powerful as WPF's XAML. XAML basics XAML has a few rules. Once we understand those rules, we can read and write any XAML. The most fundamental XAML rules are as follows: An XML element means object creation An XML attribute means setting a property (or an event handler) With these two rules, the following markup means creating a Button object and setting its Content property to the string Click me: <Button Content="Click me!" /> The equivalent C++ code would be as follows: auto b = ref new Button;b->Content = "Click me"; When creating a new Blank App project, a MainPage.xaml file is created along with the header and implementation files. Here's how that XAML file looks: <Pagex:Class="BasicXaml.MainPage"mc:Ignorable="d"><Grid Background="{StaticResourceApplicationPageBackgroundThemeBrush}"></Grid></Page> It's worth going over these lines in detail. In this example, the project name is BasicXaml. The root element is Page and an x:Class attribute is set, indicating the class that inherits from Page, here named BasicXaml::MainPage. Note that the class name is the full name including namespace, where the separator must be a period (not the C++ scope resolution operator ::). x:Class can only be placed on the root element. What follows that root element is a bunch of XML namespace declarations. These give context to the elements used in the entire XAML of this page. The default XML namespace (without a name) indicates to the XAML parser that types such as Page, Button, and Grid can be written as they are, without any special prefix. This is the most common scenario, because most of the XAML in a page constitutes user interface elements. The next XML namespace prefix is x and it points to special instructions for the XAML parser. We have just seen x:Classin action. We'll meet other such attributes later in this article. Next up is a prefix named local, which points to the types declared in the BasicXaml namespace. This allows creating our own objects in XAML; the prefix of such types must be local so that the XAML parser understands where to look for such a type (of course, we can change that to anything we like). For example, suppose we create a user control derived type named MyControl. To create a MyControl instance in XAML, we could use the following markup: <local:MyControl /> The d prefix is used for designer-related attributes, mostly useful with Expression Blend. The mc:ignorable attribute states that the d prefix should be ignored by the XAML parser (because it's related to the way Blend works with the XAML). The Grid element is hosted inside the Page, where "hosted" will become clear in a moment. Its Background property is set to {StaticResource ApplicationPageBackgroundThemeBrush}. This is a markup extension, discussed in a later section in this article. XAML is unable to invoke methods directly; it can just set properties. This is understandable, as XAML needs to remain declarative in nature; it's not meant as a replacement for C++ or any other programming language. Type converters XML deals with strings. However, it's clear that many properties are not strings. Many can still be specified as strings, and still work correctly thanks to the type converters employed by the XAML parser. Here's an example of a Rectangle element: <Rectangle Fill="Red" /> Presumably, the Fill property is not of a string type. In fact, it's a Brush. Red here really means ref new SolidColorBrush(Colors::Red). The XAML parser knows how to translate a string, such as Red (and many others) to a Brush type (in this case the more specific SolidColorBrush). Type converters are just one aspect of XAML that make it more succinct than the equivalent C++ code. Complex properties As we've seen, setting properties is done via XML attributes. What about complex properties that cannot be expressed as a string and don't have type converters? In this case, an extended syntax (property element syntax) is used to set the property. Here's an example: <Rectangle Fill="Red"><Rectangle.RenderTransform><RotateTransform Angle="45" /></Rectangle.RenderTransform></Rectangle> Setting the RenderTransform property cannot be done with a simple string; it must be an object that is derived from the Transform class (RotateTransform in this case). The preceding markup is equivalent to the following C++ code: auto r = ref new Rectangle;r->Fill = ref new SolidColorBrush(Colors::Red);auto rotate = ref new RotateTransform();rotate->Angle = 45;r->RenderTransform = rotate; Dependency properties and attached properties Most propertieson various elements and controls are not normal, in the sense that they are not simple wrappers around private fields. It's important to realize that there is no difference in XAML between a dependency property and a regular property; the syntax is the same. In fact, there is no way to tell if a certain property is a dependency property or not, just by looking at its use in XAML. Dependency properties provide the following features Change notifications when the property value changes Visual inheritance for certain properties (mostly the font-related properties) Multiple providers that may affect the final value (one wins out) Memory conservation (value not allocated unless changed) Some WinRT features, such as data binding, styles, and animations are dependent on that support. Another kind of dependency properties is attached properties. But essentially an attached property is contextual—it's defined by one type, but can be used by any type that inherits from DependencyObject (as all elements and controls do). Since this kind of property is not defined by the object it's used on,it merits a special syntax in XAML. The following is an example of a Canvaspanel that holds two elements: <Canvas><Rectangle Fill="Red" Canvas.Left="120" Canvas.Top="40"Width="100" Height="50"/><Ellipse Fill="Blue" Canvas.Left="30" Canvas.Top="90"Width="80" Height="80" /></Canvas> The Canvas.Left and Canvas.Top are attached properties. They were defined by the Canvas class, but they are attached to the Rectangle and Ellipse elements. Attached properties only have meaning in certain scenarios. In this case, they indicate the exact position of the elements within the canvas .The canvas is the one that looks for these properties in the layout phase.This means that if those same elements were placed in, say a Grid, those properties would have no effect, because there is no interested entity in those properties (there is no harm in having them, however). Attached properties can be thought of as dynamic properties that may or may not be set on objects. This is the resulting UI: Setting an attached property in code is a little verbose. Here's the equivalent C++ code for setting the Canvas.Left and Canvas.Top properties on an element named _myrect: Canvas::SetLeft(_myrect, 120);Canvas::SetTop(_myrect, 40); Content properties The relationship between a Page object and a Grid object is not obvious. Grid seems to be inside the Page. But how would that translate to code? The Page/Grid markup can be summed up as follows (ignoring the detailed markup): <Page><Grid Background="..."></Grid></Page> This is actually a shortcut for the following markup: <Page><Page.Content><Grid Background="..."></Grid></Page.Content></Page> This means the Grid object is set as the Content property of the Page object; now the relationship is clear. The XAML parser considers certain properties (no more than one per type hierarchy) as the default or content properties. It doesn't have to be named Content, but it is in the Page case. This attribute is specified in the control's metadata using the Windows::UI::Xaml::Markup::ContentAttribute class attribute. Looking at the Visual Studio object browser for the Page class shows no such attribute. But Page inherits from UserControl; navigating to UserControl, we can see the attribute set: Attributes are a way to extend the metadata for a type declaratively. They can be inserted in C++/CX by an attribute type name in square brackets before the item that attribute is applied to (can be a class, interface, method, property, and other code element). An attribute class must derive from Platform::Metadata::Attribute to be considered as such by the compiler. Some of the common ContentProperty properties in WinRT types are as follows: Content of ContentControl (and all derived types) Content of UserControl Children of Panel (base class for all layout containers) Items of ItemsControl (base class for collection-based controls) GradientStops of GradientBrush (base class of LinearGradientBrush) Collection properties Some properties are collections (of type IVector<T> or IMap<K,V>, for instance).Such properties can be filled with objects, and the XAML parser will call the IVector<T>::Append or IMap<K,V>::Insert methods. Here's an example for a LinearGradientBrush: <Rectangle><Rectangle.Fill><LinearGradientBrush EndPoint="1,0"><GradientStop Offset="0" Color="Red" /><GradientStop Offset=".5" Color="Yellow" /><GradientStop Offset="1" Color="Blue" /></LinearGradientBrush></Rectangle.Fill></Rectangle> Two rules are at work here. The first is the ContentProperty of LinearGradientBrush (GradientStops), which need not be specified. It's of the type GradientStopCollection, which implements IVector<GradientStop>, and thus is eligible for automatic appending. This is equivalent to the following code: auto r = ref new Rectangle;auto brush = ref new LinearGradientBrush;brush->EndPoint = Point(1.0, 0);auto stop = ref new GradientStop;stop->Offset = 0; stop->Color = Colors::Red;brush->GradientStops->Append(stop);stop = ref new GradientStop;stop->Offset = 0.5; stop->Color = Colors::Yellow;brush->GradientStops->Append(stop);stop = ref new GradientStop;stop->Offset = 1; stop->Color = Colors::Blue;brush->GradientStops->Append(stop);r->Fill = brush; This is perhaps the first clear sign of XAML syntax advantage over C++. Here's the rectangle in all its glory: In the case of IMap<K,V>, an attribute named x:Key must be set on each item to indicate the key sent to the IMap<K,V>::Insert method. We'll see an example of such a map later in this article, when we will discuss resources. Markup extensions Markup extensions are special instructions to the XAML parser that provide ways of expressing things that are beyond object creation or setting some property. These instructions are still declarative in nature, but their code equivalent usually entails calling methods, which is not directly possible in XAML. Markup extensions are placed inside curly braces as property values. They may contain arguments and properties, as we'll see in later chapters. The only markup extension used by default in a blank page is {StaticResource}, which will be discussed later in this article. WPF and Silverlight 5 allow developers to create custom markup extensions by deriving classes from MarkupExtension. This capability is unavailable in the current WinRT implementation. One simple example of a markup extension is {x:Null}. This is used in XAML whenever the value nullptr needs to be specified, as there's no better way to use a string for this. The following example makes a hole in the Rectangle element: <Rectangle Stroke="Red" StrokeThickness="10" Fill="{x:Null}" /> Naming elements Objects created through XAML can be named using the x:Name XAML attribute. Here's an example: <Rectangle x_Name="r1">…</Rectangle> The net result is a private member variable (field) that is created by the XAML compiler inside MainPage.g.h (if working on MainPage.xaml): private: ::Windows::UI::Xaml::Shapes::Rectangle^ r1; The reference in itself must be set in the implementation of MainPage::InitializeComponent with the following code: // Get the Rectangle named 'r1'r1 = safe_cast<::Windows::UI::Xaml::Shapes::Rectangle^>(static_cast<Windows::UI::Xaml::IFrameworkElement^>(this)->FindName(L"r1")); The mentioned file and method are discussed further in the section XAML compilation and execution. Regardless of how it works, r1 is now a reference to that particular rectangle. Connecting events to handlers Events can be connected to handlers by using the same syntax as setting properties, but in this case the value of the property must be a method in the code behind class with the correct delegate signature. Visual Studio helps out by adding a method automatically if Tab is pressed twice after entering the event name (in the header and implementation files). The default name that Visual Studio uses includes the element's name (x:Name) if it has one, or its type if it doesn't, followed by an underscore and the event name, and optionally followed by an underscore and an index if duplication is detected. The default name is usually not desirable; a better approach that still has Visual Studio creating the correct prototype is to write the handler name as we want it, and then right-click on the handler name and select Navigate to Event Handler. This has the effect of creating the handler (if it does not exist) and switching to the method implementation. Here's an example of an XAML event connection: <Button Content="Change" Click="OnChange" /> And the handler would be as follows (assuming the XAML is in MainPage.xaml): void MainPage::OnChange(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e){} Visual Studio also writes the namespace name in front of the class name (deleted in the preceding code example); this can be deleted safely, since an in-use namespace statement exists at the top of the file for the correct namespace. Also, the usage of Platform::Object instead of just Object (and similarly for RoutedEventArgs) is less readable; the namespace prefixes can be removed, as they are set up at the top of the file by default. All events (by convention) use delegates that are similar. The first argument is always the sender of the event (in this case a Button) and the second parameter is the extra information regarding the event. RoutedEventArgs is the minimum type for events, known as routed events. A detailed discussion of routed events is covered in the next article. XAML rules summary This is a summary of all XAML rules: An XAML element means creating an instance. An XAML attribute sets a property or an event handler. For properties, a type converter may execute depending on the property's type. Complex properties are set with the Type.Property element syntax. Attached properties are set with the Type.Property syntax, where Type is the declaring type of the attached property. ContentPropertyAttribute sets a Content property that need not be specified. Properties that are collections cause the XAML parser to call Append or Insert, as appropriate, automatically. Markup extensions allow for special (predefined) instructions. Introducing the Blend for Visual Studio 2012 tool Visual Studio 2012 is installed with the Blend for Visual Studio 2012 tool. This tool is typically used by UI designers to create or manipulate the user interface for XAML-based applications. The initial release of Blend for Visual Studio 2012 only supported Windows 8 Store Apps and Windows Phone 8 projects. The support for WPF 4.5 and Silverlight was added in Update 2 for Visual Studio 2012. Blend can be used alongside Visual Studio 2012, as both understand the same file types (such as solution .sln files). It's not atypical to switch back and forth between the two tools—using each tool for its strengths. Here's a screenshot of Blend with the CH03.sln solution file open (the solution that holds all the samples for this article): The preceding screenshot shows a particular XAML file open, with one button selected. Several windows comprise Blend, some of which are similar to their Visual Studio counterparts, namely Projects and Properties. Some of the new windows include: Assets: Holds the elements and controls available in WinRT (along with some other useful shortcuts) Objects and Timeline: Include all objects in the visual tree and also animations Resources: Holds all resources (refer to the next section) within the application Blend's design surface allows manipulating elements and controls, which is also possible to do in Visual Studio. Blend's layout and some special editing features make it easier for UI/graphic designers to work with as it mimics other popular applications, such as Adobe Photoshop and Illustrator. Any changes made using the designer are immediately reflected by the changed XAML. Switching back to Visual Studio and accepting the reload option synchronizes the files; naturally, this can be done both ways. It's possible to work from within Blend entirely. Pressing F5 builds and launches the app in the usual way. Blend, however, is not Visual Studio, and breakpoints and other debugging tasks are not supported. Blend is a non-trivial tool, and is well beyond the scope of this book. Experimentation can go a long way, however. XAML compilation and execution The XAML compiler that runs as part of the normal compilation process, places the XAML as an internal resource within the EXE or DLL. In the constructor of a XAML root element type (such as MainPage), a call is made to InitializeComponent. This method uses a static helper method Application::LoadComponent to load the XAML and parse it—creating objects, setting properties, and so on. Here's the implementation created by the compiler for InitializeComponent (in MainPage.g.hpp, with some code cleaning): void MainPage::InitializeComponent() {if (_contentLoaded)return;_contentLoaded = true;// Call LoadComponent on ms-appx:///MainPage.xamlApplication::LoadComponent(this,ref new ::Windows::Foundation::Uri(L"ms-appx:///MainPage.xaml"),ComponentResourceLocation::Application);} Connecting XAML, H, and CPP files to the build process From a developer's perspective, working with a XAML file carries with it two other files, the H and CPP. Let's examine them in a little more detail. Here's the default MainPage.xaml.h (comments and namespaces removed): #include "MainPage.g.h"namespace BasicXaml {public ref class MainPage sealed {public:MainPage();protected:virtual void OnNavigatedTo(NavigationEventArgs^ e)override;};} The code shows a constructor and a virtual method override named OnNavigatedTo (unimportant for this discussion). One thing that seems to be missing is the InitializeComponent method declaration mentioned in the previous section. Also the inheritance from Page that was hinted at earlier is missing. It turns out that the XAML compiler generates another header file named MainPage.g.h (g stands for generated) based on the XAML itself (this is evident with the top #include declaration). This file contains the following (it can be opened easily by selecting the Project | Show All Files, or the equivalent toolbar button, or right clicking on #include and selecting Open Document…): namespace BasicXaml {partial ref class MainPage : public Page,public IComponentConnector {public:void InitializeComponent();virtual void Connect(int connectionId, Object^ target);private:bool _contentLoaded;};} Here we find the missing pieces. Here we find InitializeComponent, as well as the derivation from Page. How can there be more than one header file per class? A new C++/CX feature called partial classes allows this. The MainPage class is marked as partial, meaning there are more parts to it. The last part should not be marked as partial, and should include at least one header so that a chain forms, eventually including all the partial headers; all these headers must be part of the same compilation unit (a CPP file). This MainPage.g.h file is generated before any compilation happens; it's generated on the fly while editing the XAML file. This is important because named elements are declared in that file, providing instance intellisense. During the compilation process, MainPage.cpp is finally compiled, producing an object file, MainPage.obj. It still has some unresolved functions, such as InitializeComponent. At this time, MainPage.obj (along with other XAML object files, if exist) is used to generate the metadata (.winmd) file. To complete the build process, the compiler generates MainPage.g.hpp, which is actually an implementation file, created based on the information extracted from the metadata file (the InitializeComponentimplementation is generated in this file). This generated file is included just once in a file called XamlTypeInfo.g.cpp, which is also generated automatically based on the metadata file, but that's good enough so that MainPage.g.hppis finally compiled, allowing linking to occur correctly. Resources The term "resources" is highly overloaded. In classic Win32 programming, resources refer to read-only chunks of data, used by an application. Typical Win32 resources are strings, bitmaps, menus, toolbars, and dialogs, but custom resources can be created as well, making Win32 treat those as unknown chunks of binary data. WinRT defines binary, string, and logical resources. The following sections discuss binary and logical resources (string resources are useful for localization scenarios and will not be discussed in this section). Binary resources Binary resources refer to chunks of data, provided as part of the application's package. These typically include images, fonts, and any other static data needed for the application to function correctly. Binary resources can be added to a project by right-clicking on the project in Solution Explorer, and selecting Add Existing Item. Then, select a file that must be in the project's directory or in a subdirectory. Contrary to C# or VB projects, adding an existing item from a location does not copy the file to the project's directory. This inconsistency is a bit annoying for those familiar with C#/VB projects, and hopefully will be reconciled in a future Visual Studio version or service pack. A typical Store app project already has some binary resources stored in the Assets project folder, namely images used by the application: Using folders is a good way to organize resources by type or usage. Right-clicking on the project node and selecting Add New Filter creates a logical folder, to which items may be dragged. Again, contrary to C#/VB projects, project folders are not created in the filesystem. It's recommended that these are actually created in the filesystem for better organization. The added binary resource is packaged as part of the application's package and is available in the executable folder or subfolder, keeping its relative location. Rightclicking on such a resource and selecting Properties yields the following dialog: The Content attribute must be set to Yes for the resource to be actually available (the default). Item Type is typically recognized by Visual Studio automatically. In case, it doesn't, we can always set it to Text and do whatever we want with it in code. Don't set Item Type to Resource. This is unsupported in WinRT and will cause compile errors (this setting is really for WPF/Silverlight). Binary resources can be accessed in XAML or in code, depending on the need. Here's an example of using an image named apple.png stored in a subfolder in the application named Images under the Assets folder by an Image element: <Image Source="/Assets/Images/apple.png" /> Note the relative URI. The preceding markup works because of a type converter that's used or the Image::Source property (which is of the type ImageSource). That path is really a shortcut for the following, equivalent, URI: <Image Source="ms-appx:///Assets/Images/apple.png" /> Other properties may require a slightly different syntax, but all originate through the ms-appx scheme, indicating the root of the application's package. Binary resources that are stored in another component referenced by the application can be accessed with the following syntax: <Image Source="/ResourceLibrary/jellyfish.jpg" /> The markup assumes that a component DLL named ResourceLibrary.Dll is referenced by the application and that a binary resource named jellyfish.jpg is present in its root folder. Logical resources Binary resources are not new or unique to Store apps. They've been around practically forever. Logical resources, on the other hand, is a more recent addition. First created and used by WPF, followed by the various versions of Silverlight, they are used in WinRT as well. So, what are they? Logical resources can be almost anything. These are objects, not binary chunks of data. They are stored in the ResourceDictionary objects, and can be easily accessed in XAML by using the StaticResource markup extension. Here's an example of two elements that use an identical brush: <Ellipse Grid.Row="0" Grid.Column="1"><Ellipse.Fill><LinearGradientBrush EndPoint="0,1"><GradientStop Offset="0" Color="Green" /><GradientStop Offset=".5" Color="Orange" /><GradientStop Offset="1" Color="DarkRed" /></LinearGradientBrush></Ellipse.Fill></Ellipse><Rectangle Grid.Row="1" Grid.Column="1" StrokeThickness="20"><Rectangle.Stroke><LinearGradientBrush EndPoint="0,1"><GradientStop Offset="0" Color="Green" /><GradientStop Offset=".5" Color="Orange" /><GradientStop Offset="1" Color="DarkRed" /></LinearGradientBrush></Rectangle.Stroke></Rectangle> The problem should be self-evident. We're using the same brush twice. This is bad for two reasons: If we want to change the brush, we need to do it twice (because of the duplication). Naturally, this is more severe if that brush is used by more than two elements. Two different objects are created, although just one shared object is needed. LinearGradientBrush can be turned into a logical resource (or simply a resource) and referenced by any element that requires it. To do that, the brush must be placed in a ResourceDictionary object. Fortunately, every element has a Resources property (of type ResourceDictionary) that we can use. This is typically done on the root XAML element (typically a Page), or (as we'll see in a moment) in the application's XAML (App.Xaml): <Page.Resources><LinearGradientBrush x_Key="brush1" EndPoint="0,1"><GradientStop Offset="0" Color="Green" /><GradientStop Offset=".5" Color="Orange" /><GradientStop Offset="1" Color="DarkRed" /></LinearGradientBrush></Page.Resources> Any logical resource must have a key, because it's in a dictionary. That key is specified by the x:Key XAML directive. Once placed, a resource can be accessed from any element within that Page with the StaticResource markup extension as follows: <Ellipse Fill="{StaticResource brush1}" /><Rectangle Stroke="{StaticResource brush1}" StrokeThickness="40" /> The StaticResource markup extension searches for a resource with the specified key starting from the current element. If not found, the search continues on the resources with its parent element (say a Grid). If found, the resource is selected (it is created the first time it's requested), and StaticResource is done. If not found, the parent's parent is searched and so on. If the resource is not found at the top level element (typically a Page, but can be a UserControl or something else), the search continues in the application resources (App.xaml). If not found, an exception is thrown. The search process can be summarized by the following diagram: Why is the markup extension called StaticResource? Is there a DynamicResource? DynamicResource exists in WPF only, which allows a resource to be replaced dynamically, with all those bound to it noticing the change. This is currently unsupported by WinRT. There is no single call that is equivalent to StaticResource, although it's not difficult to create one if needed. The FrameworkElement::Resources property can be consulted on any required level, navigating to the parent element using the Parent property. The Application::Resources property has special significance, since any resources defined within it can be referenced by any page or element across the entire application. This is typically used to set various defaults for a consistent look and feel. It may be tempting to store actual elements as resources (such as buttons). This should be avoided because resources are singletons within their usage container; this means referencing that button more than once within the same page will cause an exception to be thrown on the second reference, because an element can be in the visual tree just once. Resources are really intended for sharable objects, such as brushes, animations, styles, and templates. Resources can be added dynamically by using the ResourceDictionary::Insert method (on the relevant ResourceDictionary) and removed by calling ResourceDictionary::Remove. This only has an effect on subsequent {StaticResource} invocations; already bound resources are unaffected. A StaticResource markup extension can be used by a resource as well. For this to work, any StaticResource must reference a resource that was defined earlier in the XAML; this is due to the way the XAML parser works. It cannot find resources that it has not yet encountered. Managing logical resources Logical resources may be of various types, such as brushes, geometries, styles, templates, and more. Placing all those resources in a single file, such as App.xaml, hinders maintainability. A better approach would be to separate resources of different types (or based on some other criteria) from their own files. Still, they must be referenced somehow from within a common file such as App.xaml so that they are recognized. ResourceDictionary can incorporate other resource dictionaries using its MergedDictionaries property (a collection). This means a ResourceDictionary can reference as many resource dictionaries as desired and can have its own resources as well. The Source property must point to the location of ResourceDictionary. The default App.xaml created by Visual Studio contains the following (comments removed): <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionarySource="Common/StandardStyles.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources> Indeed, we find a file called StandardStyles.xaml in the Common folder, which hosts a bunch of logical resources, with ResourceDictionary as its root element. For this file to be considered when StaticResource is invoked, it must be referenced by another ResourceDictionary, from a Page or the application (the application is more common). The ResourceDictionary::MergedDictionaries property contains other ResourceDictionary objects, whose Source property must point to the required XAML to be included (that XAML must have ResourceDictionary as its root element). We can create our own ResourceDictionary XAML by using Visual Studio's Add New Item menu option and selecting Resource Dictionary: Duplicate keys No two objects can have the same key in the same ResourceDictionary instance. StaticResource takes the first resource it finds with the specified key, even if that key already exists in a ResourceDictionary. What about merged dictionaries? Merging different resource dictionaries may cause an issue—two or more resources with the same key that originate from different merged dictionaries. This is not an error and does not throw an exception. Instead, the selected object is the one from the last resource dictionary added (which has a resource with that key). Furthermore, if a resource in the current resource dictionary has the same key as any of the resources in its merged dictionaries, it always wins out. Here's an example: <ResourceDictionary><SolidColorBrush Color="Blue" x_Key="brush1" /><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Resources/Brushes2.xaml" /><ResourceDictionary Source="Resources/Brushes1.xaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary> Given this markup, the resource named brush1 is a blue SolidColorBrush because it appears in the ResourceDictionary itself. This overrides any resources named brush1 in the merged dictionaries. If this blue brush did not exist, brush1 would be looked up in Brushes1.xaml first, as this is the last entry in the merged dictionaries collection. XAML containing a ResourceDictionary as its root can be loaded dynamically from a string using the static XamlReader::Load method and then added as a merged dictionary, where appropriate. Styles Consistency in user interface is an important trait; there are many facets of consistency, one of which is the consistent look and feel of controls. For example, all buttons should look roughly the same—similar colors, fonts, sizes, and so on. Styles provide a convenient way of grouping a set of properties under a single object, and then selectively (or automatically, as we'll see later) apply it to elements. Styles are always defined as resources (usually at the application level, but can also be at the Page or UserControl level). Once defined, they can be applied to elements by setting the FrameworkElement::Style property. Here's a style defined as part of the Resources section of a Page: <Page.Resources><Style TargetType="Button" x_Key="style1"><Setter Property="FontSize" Value="40" /><Setter Property="Background"><Setter.Value><LinearGradientBrush ><GradientStop Offset="0" Color="Yellow" /><GradientStop Offset="1" Color="Orange" /></LinearGradientBrush></Setter.Value></Setter><Setter Property="Foreground" Value="DarkBlue" /></Style></Page.Resources> The style has a key (style1), and must have TargetType. This is the type the style may be applied to (and any derived types). The XAML parser has a type converter that converts TargetType to a TypeName object. The main ingredient in Style is its Setters collection (which is also its ContentProperty). This collection accepts Setter objects, which need Property and Value. The property must be a dependency property (not usually a problem, as most element properties are dependency properties); these are provided as simple strings thanks to type converters used behind the scene. The above markup sets up the properties FontSize, Background (with a complex property syntax because of the LinearGradientBrush), and Foreground—all for the Button controls. Once defined, the style can be applied to elements using the usual StaticResource markup extension in XAML by setting the FrameworkElement::Style property, as in the following example: <Button Content="Styled button" Style="{StaticResource style1}" /> Readers familiar with WPF may be wondering if the TargetType property can be omitted so that a greater control range can be covered. This is unsupported in the current version of WinRT. Setting the style on an incompatible element type (such as a CheckBox control in this example) causes an exception to be thrown at page load time. If a CheckBox should also be able to use the same style, the TargetType can be changed to ButtonBase (which covers all button types). Use different styles for different elements, even if a base type seems to cover several controls. It's very likely that later some properties may need to be tweaked for a particular type, making it difficult to change the style. Build a different style for different concrete types. You can also use style inheritance (as described later) to shorten some of the markup. What happens if an element with an applied style sets a property to a different value than the one from Style? The local value wins out. This means that the following button has a font size of 30 and not 40: <Button Content="Styled button" FontSize="30"Style="{StaticResource style1}" /> Implicit (automatic) styles The previous section showed how to create a style that has a name (x:Key) and how to apply it to elements. Sometimes, however, we would like a style to be applied automatically to all elements of a certain type, to give the application a consistent look. For example, we may want all buttons to have a certain font size or background, without the need for setting the Style property of each and every button. This makes creating new buttons easier, as the developer/designer doesn't have to know what style to apply (if any, the implicit style in scope will be used automatically). To create a Style that is applied automatically, the x:Key attribute must be removed: <Style TargetType="Button">…</Style> The key still exists, as the Style property is still part of ResourceDictionary (which implements IMap<Object, Object>), but is automatically set to a TypeName object for the specified TargetType. Once the Style property is defined and any Button element (in this example) in scope for ResourceDictionary of the Style property is in, that style will be applied automatically. The element can still override any property it wishes by setting a local value. Automatic styles are applied to the exact type only, not to derived types. This means that an automatic style for ButtonBase is useless, as it's an abstract class. An element may wish to revert to its default style and not have an implicit style applied automatically. This can be achieved by setting FrameworkElement::Style to nullptr (x:Null in XAML). Style inheritance Styles support the notion of inheritance, somewhat similar to the same concept in object orientation. This is done using the BasedOn property that must point to another style to inherit from. The TargetType of the derived style must be the same as in the base style. An inherited style can add Setter objects for new properties to set, or it can provide a different value for a property that was set by the base style. Here's an example for a base style of a button: <Style TargetType="Button" x_Key="buttonBaseStyle"><Setter Property="FontSize" Value="70" /><Setter Property="Margin" Value="4" /><Setter Property="Padding" Value="40,10" /><Setter Property="HorizontalAlignment" Value="Stretch" /></Style> The following markup creates three inherited styles: <Style TargetType="Button" x_Key="numericStyle"BasedOn="{StaticResource buttonBaseStyle}"><Setter Property="Background" Value="Blue" /><Setter Property="Foreground" Value="White" /></Style><Style TargetType="Button" x_Key="operatorStyle"BasedOn="{StaticResource buttonBaseStyle}"><Setter Property="Background" Value="Orange" /><Setter Property="Foreground" Value="Black" /></Style><Style TargetType="Button" x_Key="specialStyle"BasedOn="{StaticResource buttonBaseStyle}"><Setter Property="Background" Value="Red" /><Setter Property="Foreground" Value="White" /></Style> These styles are part of a simple integer calculator application. The calculator looks like this when running: Most of the elements comprising the calculator are buttons. Here is the numeric button markup: <Button Style="{StaticResource numericStyle}" Grid.Row="1"Content="7" Click="OnNumericClick" /><Button Style="{StaticResource numericStyle}" Grid.Row="1"Grid.Column="1" Content="8" Click="OnNumericClick"/><Button Style="{StaticResource numericStyle}" Grid.Row="1"Grid.Column="2" Content="9" Click="OnNumericClick"/> The operator buttons simply use a different style: <Button Style="{StaticResource operatorStyle}" Grid.Row="3"Grid.Column="3" Content="-" Click="OnOperatorClick"/><Button Style="{StaticResource operatorStyle}" Grid.Row="4"Grid.Column="3" Content="+" Grid.ColumnSpan="2"Click="OnOperatorClick"/> The = button uses the same style as operators, but changes its background by setting a local value: <Button Style="{StaticResource operatorStyle}" Grid.Row="4"Grid.Column="1" Grid.ColumnSpan="2" Content="="Background="Green" Click="OnCalculate"/> The complete project is named StyledCalculator and can be found as part of the downloadable source for this article. Style inheritance may seem very useful, but should be used with caution. It suffers from the same issues as object oriented inheritance in a deep inheritance hierarchy—a change in a base style up in the hierarchy can affect a lot of styles, being somewhat unpredictable, leading to a maintenance nightmare. Thus, a good rule of thumb to use is to have no more than two inheritance levels. Any more than that may cause things to get out of hand. Store application styles A Store app project created by Visual Studio has a default style file named StandardStyles.xaml in the Common folder. The file includes styles for all common elements and controls the set up for a common look and feel that is recommended as a starting point. It's certainly possible to change these styles or to inherit from them if needed. WinRT styles are similar in concept to CSS used in web development to provide styling to HTML pages. The cascading part hints to the multilevel nature of CSS, much like the multilevel nature of WinRT styles (application, page, panel, specific element, and so on). Summary This article was all about XAML, the declarative language used to build user interfaces for Windows Store apps. XAML takes some time getting used to it, but its declarative nature and markup extensions cannot easily be matched by procedural code in C++ (or other languages). Designer-oriented tools, such as Expression Blend and even the Visual Studio designer make it relatively easy to manipulate XAML without actually writing XAML, but as developers and designers working with other XAML-based technologies have already realized, it's sometimes necessary to write XAML by hand, making it an important skill to acquire. Resources for Article : Further resources on this subject: WPF 4.5 Application and Windows [Article] Android Native Application API [Article] Working with Apps in Splunk [Article]
Read more
  • 0
  • 0
  • 4266

article-image-introduction-legacy-modernization-oracle
Packt
16 Oct 2009
13 min read
Save for later

Introduction to Legacy Modernization in Oracle

Packt
16 Oct 2009
13 min read
IT organizations are under increasing demand to increase the ability of the business to innovate while controlling and often reducing costs. Legacy modernization is a real opportunity for these goals to be achieved. To attain these goals, the organization needs to take full advantage of emerging advances in platform and software innovations, while leveraging the investment that has been made in the business processes within the legacy environment.To make good choices for a specific roadmap to modernization, the decision makers should work to have a good understanding of what these modernization options are, and how to get there. Overview of the Modernization Options There are five primary approaches to legacy modernization: Re-architecting to a new environment SOA integration and enablement Replatforming through re-hosting and automated migration Replacement with COTS solutions Data Modernization Other organizations may have different nomenclature for what they call each type of modernization, but any of these options can generally fit into one of these five categories. Each of the options can be carried out in concert with the others, or as a standalone effort. They are not mutually exclusive endeavors. Further, in a large modernization project, multiple approaches are often used for parts of the larger modernization initiative. The right mix of approaches is determined by the business needs driving the modernization, organization's risk tolerance and time constraints, the nature of the source environment and legacy applications. Where the applications no longer meet business needs and require significant changes, re-architecture might be the best way forward. On the other hand, for very large applications that mostly meet the business needs, SOA enablement or re-platforming might be lower risk options. You will notice that the first thing we talk about in this section—the Legacy Understanding phase—isn't listed as one of the modernization options. It is mentioned at this stage because it is a critical step that is done as a precursor to any option your organization chooses. Legacy Understanding Once we have identified our business drivers and the first steps in this process, we must understand what we have before we go ahead and modernize it. Legacy environments are very complex and quite often have little or no current documentation. This introduces a concept of analysis and discovery that is valuable for any modernization technique. Application Portfolio Analysis (APA) In order to make use of any modernization approach, the first step an organization must take is to carry out an APA of the current applications and their environment. This process has many names. You may hear terms such as Legacy Understanding, Application Re-learn, or Portfolio Understanding. All these activities provide a clear view of the current state of the computing environment. This process equips the organization with the information that it needs to identify the best areas for modernization. For example, this process can reveal process flows, data flows, how screens interact with transactions and programs, program complexity and maintainability metrics and can even generate pseudocode to re-document candidate business rules. Additionally, the physical repositories that are created as a result of the analysis can be used in the next stages of modernization, be it in SOA enablement, re-architecture, or re-platforming. Efforts are currently underway by the Object Management Group (OMG) to create a standard method to exchange this data between applications. The following screenshot shows the Legacy Portfolio Analysis: APA Macroanalysis The first form of APA analysis is a very high-level abstract view of the application environment. This level of analytics looks at the application in the context of the overall IT organization. Systems information is collected at a very high level. The key here is to understand which applications exist, how they interact, and what the identified value of the desired function is. With this type of analysis, organizations can manage overall modernization strategies and identify key applications that are good candidates for SOA integration, re-architecture, or re-platforming versus a replacement with Commercial Off-the-Shelf (COTS) applications. Data structures, program code, and technical characteristics are not analyzed here. The following macro-level process flow diagram was automatically generated from Relativity Technologies Modernization Workbench tool. Using this, the user can automatically get a view of the screen flows within a COBOL application. This is used to help identify candidate areas for modernization, areas of complexity, transfer of knowledge, or legacy system documentation. The key thing about these types of reports is that they are dynamic and automatically generated. The previous flow diagram illustrates some interesting points about the system that can be understood quickly by the analyst. Remember, this type of diagram is generated automatically, and can provide instant insight into the system with no prior knowledge. For example, we now have some basic information such as: MENSAT1.MENMAP1 is the main driver and is most likely a menu program. There are four called programs. Two programs have database interfaces. This is a simplistic view, but if you can imagine hundreds of programs in a visual perspective, we can quickly identify clusters of complexity, define potential subsystems, and do much more, all from an automated tool with visual navigation and powerful cross-referencing capabilities. This type of tool can also help to re-document existing legacy assets. APA Microanalysis The second type of portfolio analysis is APA microanalysis. This examines applications at the program level. This level of analysis can be used to understand things like program logic or candidate business rules for enablement, or business rule transformation. This process will also reveal things such as code complexity, data exchange schemas, and specific interaction within a screen flow. These are all critical when considering SOA integration, re-architecture, or a re-platforming project. The following are more models generated from the Relativity Modernization Technologies Workbench tool. The first is a COBOL transaction taken from a COBOL process. We are able to take a low-level view of a business rule slice taken from a COBOL program, and understand how this process flows. The particulars of this flow map diagram are not important; rather, this model can be automatically generated and is dynamic based on the current state of the code. The second model shows how a COBOL program interacts with a screen conversation. In this example, we are able to look at specific paragraphs within a particular program. We can identify specific CICS transaction and understand which paragraphs (or subroutines) are interacting with the database. The models can be used to further refine our drive for a more re-architected system, which helps us to  identify business rules and populate a rules engine, This example is just another example of a COBOL program that interacts with screens—shown in gray, and the paragraphs that execute CICS transactions—shown in white. So with these color coded boxes, we can quickly identify paragraphs, screens, databases, and CICS transactions. Application Portfolio Management (APM) APA is only a part of IT approach known as Application Portfolio Management. While APA analysis is critical for any modernization project, APM provides guideposts on how to combine the APA results, business assessment of the applications' strategic value and future needs, and IT infrastructure directions to come up with a long term application portfolio strategy and related technology targets to support it. It is often said that you cannot modernize that which you do not know. With APM, you can effectively manage change within an organization, understand the impact of change, and also manage its compliance. APM is a constant process, be it part of a modernization project or an organization's portfolio management and change control strategy. All applications are in a constant state of change. During any modernization, things are always in a state of flux. In a modernization project, legacy code is changed, new development is done (often in parallel), and data schemas are changed. When looking into APM tool offerings, consider products that can provide facilities to capture these kinds of changes in information and provide an active repository, rather than a static view. Ideally, these tools must adhere to emerging technical standards, like those being pioneered by  the OMG. Re-Architecturing Re-architecting is based on the concept that all legacy applications contain invaluable business logic and data relevant to the business, and these assets should be leveraged in the new system, rather than throwing it all out to rebuild from scratch. Since the new modern IT environment elevates a lot of this logic above the code using declarative models supported by BPM tools, ESBs, Business Rules engines, Data integration and access solutions, some of the original technical code can be replaced by these middleware tools to achieve greater agility. The following screenshot shows an example of a system after re-architecture. The previous example shows what a system would look like, from a higher level, after re-architecture. We see that this isn't a simple transformation of one code base to another in a one-to-one format. It is also much more than remediation and refactoring of the legacy code to standard java code. It is a system that fully leverages technologies suited for the required task, for example, leveraging Identity Management for security, business rules for core business, and BPEL for process flow. Thus, re-architecting focuses on recovering and reassembling the process relevant to business from a legacy application, while eliminating the technology-specific code. Here, we want to capture the value of the business process that is independent of the legacy code base, and move it into a different paradigm. Re-architecting is typically used to handle modernizations that involve changes in architecture, such as the introduction of object orientation and process-driven services. The advantage that re-architecting has over greenfield development is that re-architecting recognizes that there is information in the application code and surrounding artifacts (example, DDLs, COPYBOOKS, user training manuals) that is useful as a source for the re-architecting process, such as application process interaction, data models, and workflow. Re-architecting will usually go outside the source code of the legacy application to incorporate concepts like workflow and new functionality that were never part of the legacy application. However, it also recognized that this legacy application contains key business rules and processes that need to be harvested and brought forward. Some of the important considerations for maximizing re-use by extracting business rules from legacy applications as part of a re-architecture project include: Eliminate dead code, environmental specifics, resolve mutually exclusive logic. Identify key input/output data (parameters, screen input, DB and file records, and so on). Keep in mind many rules outside of code (for example, screen flow described in a training manual. Populate a data dictionary specific to application/industry context. Identify and tag rules based on transaction types and key data, policy parameters, key results (output data). Isolate rules into tracking repository. Combine automation and human review to track relationships, eliminate redundancies, classify and consolidate, add annotation. A parallel method of extracting knowledge from legacy applications uses modeling techniques, often based on UML. This method attempts to mine UML artifacts from the application code and related materials, and then create full-fledged models representing the complete application. Key considerations for mining models include: Convenient code representation helps to quickly filter out technical details. Allow user-selected artifacts to be quickly represented in UML entities. Allow user to add relationships and annotate the objects to assemble more complete UML model. Use external information if possible to refine use cases (screen flows) and activity diagrams—remember that some actors, flows, and so on may not appear in the code. Export to XML-based standard notation to facilitate refinement and forward-re-engineering through UML-based tools. Modernization with this method leverages the years of investment in the legacy code base, it is much less costly and less risky than starting a new application from ground zero. However, since it does involve change, it does have its risks. As a result, a number of other modernization options have been developed that involve less risk. The next set of modernization option provide a different set of benefits with respect to a fully re-architected SOA environment. The important thing is that these other techniques allow an organization to break the process of reaching the optimal modernization target into a series of phases that lower the overall risk of modernization for an organization. In the following figure, we can see that re-architecture takes a monolithic legacy system and applies technology and process to deliver a highly adaptable modern architecture. Since SOA integration is the least invasive approach to legacy application modernization, this technique allows legacy components to be used as part of an SOA infrastructure very quickly and with little risk. Further, it is often the first step in the larger modernization process. In this method, the source code remains mostly unchanged (we will talk more about that later) and the application is wrapped using SOA components, thus creating services that can be exposed and registered to an SOA management facility on a new platform, but are implemented via the exiting legacy code. The exposed services can then be re-used and combined with the results of other more invasive modernization techniques such as re-architecting. Using SOA integration, an organization can begin to make use of SOA concepts, including the orchestration of services into business processes, leaving the legacy application intact. Of course, the appropriate interfaces into the legacy application must exist and the code behind these interfaces must perform useful functions in a manner that can be packaged as services. SOA readiness assessment involves analysis of service granularity, exception handling, transaction integrity and reliability requirements, considerations of response time, message sizes, and scalability, issues of end-to-end messaging security, and requirements for services orchestration and SLA management. Following an assessment, any issues discovered need to be rectified before exposing components as services, and appropriate run-time and lifecycle governance policies created and implemented. It is important to note that there are three tiers where integration can be done: Data, Screen, and Code. So, each of the tiers, based upon the state and structure of the code, can be extended with this technique. As mentioned before, this is often the first step in modernization. In this example, we can see that the legacy systems still stay on the legacy platform. Here, we isolate and expose this information as a business service using legacy adapters. The table below lists important considerations in SOA integration and enablement projects. Criteria for identifying well defined services Represent a core enterprise function re-usable by many client applications Present a coarse-grained interface Single interaction vs. multi-screen flows UI, business logic, data access layers Exception handling-returning results without branching to another screen Discovering "Services" beyond screen flows Conversational vs. sync/async calls COMMAREA transactions (re-factored to use reasonable message size) Security policies and their enforcement RACF vs. LDAP-based or SSO mechanism End-to-end messaging security and Authentication, Authorization, Audition   Services integration and orchestration Wrapping and proxying via middle-tier gate-way vs. mainframe-based services Who's responsible for input validation? Orchestrating "composite" MF services Supporting bidirectional integration Quality of Service (QoS) requirements Response time, throughput, scalability End-to-end monitoring and SLA management Transaction integrity and global transaction coordination End-to-end monitoring and tracing Services lifecycle governance Ownership of service interfaces and change control process Service discovery (repository, tools) Orchestration, extension BPM integration
Read more
  • 0
  • 0
  • 4248

article-image-liferay-portal6-build-wap-sites-and-integrate-crm-and-netvibes-widgets
Packt
18 May 2010
8 min read
Save for later

Liferay Portal6: Build WAP sites and Integrate with CRM and Netvibes widgets

Packt
18 May 2010
8 min read
(Read more interesting articles on Liferay Portal 6 here.) WAP Liferay goes mobile! As smart-phones continue to impede the space between dialing a number, taking a picture, or discovering new music, mobile browsers offer us the next frontier in the previously desktop-exclusive market of web design. A mobile browser is a web browser designed for use on a mobile device such as a mobile phone, PDA, iPhone, which is optimized to display web content most effectively for small screens on portable devices. A WAP browser provides all of the basic services of a web browser, but is simplified to operate within the restrictions of a mobile phone, such as its smaller view screen. The websites generated by the portal go with mobile browsers, or any WAP browsers. Thus you can browse portal websites, called WAP sites, through mobile devices. Themes (look and feel of websites or WAP sites) in the portal will detect mobile devices dynamically. As mentioned earlier, each site may have its own look and feel and each page could have its own look and feel. Under the tab Look and Feel, you would see Regular Browsers and Mobile Devices, where available themes will appear. Of course, you can develop your mobile themes or WAP themes depending on your own requirements. Here we're going to discuss several existing mobile themes or WAP themes, and going further, see what themes are and how they work. Jedi Mobile theme The theme Jedi Mobile has been applied on the home page of the community Guest. As you can see, the theme Jedi Mobile takes the original Jedi theme and packs it int a bite-sized, smart-phone punch. Structure The theme Jedi Mobile has the following folder structure at $AS_WEB_APP_HOME/jedi-mobile-theme. CSS: CSS files images: Image files javascripts: JavaScript files templates: Velocity template files WEB-INF: Web info specification includes sub-folders classes, lib, and tld As you can see, web-info specification covers liferay-look-and-feel.xml,liferay-plugin-package.properties, liferay-plugin-package.xml, and web.xml. Knowing the structure of the theme would be helpful to customize that theme. How does it work? You could bring the theme Jedi Mobile Theme into the portal by following these steps: Download the WAR file ${jedi.mobile.theme.war} from http://liferay.cignex.com/palm_tree/book/0387/chapter12/jedi-mobiletheme-6.0.0.1.war Drop the WAR file ${jedi.mobile.theme.war} to the folder $LIFERAY_HOME/deploys when the portal is running Then apply the theme as the current look and feel of pages. What's happening? The theme Jedi Mobile has specified the following script at $AS_WEB_APP_HOME/jedi-mobile-theme/templates/portal_normal.vm. <script type="text/javascript">iPhone = function() {setTimeout("window.scrollTo(0,1) ", 100)}if (navigator.userAgent.indexOf('iPhone') != -1) {addEventListener("load", iPhone, false)addEventListener("onorientationchange", iPhone, false)}</script> As shown in the preceding code, it detects the navigator, whether it is an iPhone or not. iPhone theme The theme iPhone takes a much more direct approach to web applications. With its indigenous appearance and feel, the WAP site starts to feel like a playlist, user experience appears native, and navigation comes naturally. How does it work? You can bring the iPhone Theme into the portal by following these steps: Download the WAR file ${iphone.theme.war} from http://liferay.cignex.com/palm_tree/book/0387/chapter12/iphone-theme-6.0.0.1.war Drop the WAR file ${iphone.theme.war} to the folder $LIFERAY_HOME/deploy swhen the portal is running. Then apply the theme as the current look and feel of pages. What's happening? The theme iPhone introduces a new browser detection mechanism for specialized mobile functionality. If you visit the site on an iPhone, you get the bare minimum—JavaScript, HTML, and CSS. If you visit the site on a regular browser, you get all the more advanced UI features. The theme iPhone has specified the following script at $AS_WEB_APP_HOME/iphonetheme/templates/portal_normal.vm. #set ($isIphone = $request.getHeader("User-Agent").toLowerCase().indexOf("iphone") != -1)<!-- ignore details -->#if ($isIphone)<!-- ignore details -->#else$theme.include($top_head_include)#end</head><!-- ignore details --> iPhone Redirect theme The theme iPhone Redirect takes the browser detection mechanism and takes intelligent redirection. The theme iPhone Redirect is an unstyled theme, coming with a custom initialization feature—that is, it can detect an iPhone browser visiting the page, check for a Mobile community, and automatically redirect the iPhone user to that community if found. Moreover, it will work with a virtual host. How does it work? You could bring the theme iPhone Redirect Theme into the portal by following these steps: Download the WAR file ${iphone.redirect.theme.war} fromhttp://liferay.cignex.com/palm_tree/book/0387/chapter12/so-theme-6.0.0.1.war Drop the WAR file ${iphone. redirect.theme.war} to the folder$LIFERAY_HOME/deploy when the portal is running.   Then apply the theme as the current look and feel of pages. What's happening? The theme iPhone Redirect has the following code specified at $AS_WEB_APP_HOME/iphone-detect-theme/templates/init_custom.vm. //ignore details#set ($isIphone = $request.getHeader("User-Agent").toLowerCase().indexOf("iphone") != -1)#if ($isIphone && $mobileGroup && $group_id != $mobileGroup.groupId)<script type="text/javascript">window.location.href = '${layoutSet.virtualHost}' ? 'http://' +'${layoutSet.virtualHost}' + ((window.location.port) ? ':' + window.location.port : '') : '/web${mobileGroup.friendlyURL}'</script>#end Of course, you could customize the preceding themes according to your own requirements. Reporting JasperReports is an open source Java reporting tool that can write to screen, a printer, or to PDF, HTML, Microsoft Excel, RTF, ODT, CSV (Comma Separated Value) formats, and XML files. It can be used in Java-enabled applications, including Java EE or Web applications to generate dynamic content. It reads its instructions from an XML or .jasper file. Refer to http://www.jasperforge.org/jasperreports for more information. The portal provides full integration of JasperReports with the reporting framework—a web called reporting-jasper-web and a portlet called reports-console-portlet. The portal provides the ability to schedule reports and deliver them via Document Library and e-mail. In addition, the portal has added support for Jasper XLS data source to a reporting framework. JasperReports Engine The Liferay JasperReports Report Engine provides implementation of Liferay BI using Jasper. You can bring the web Reporting Jasper into the portal by following these steps: Download the WAR file ${reporting.jasper.web.war} from http://liferay.cignex.com/palm_tree/book/0387/chapter12/reporting-jasper-web-6.0.0.1.war Drop the WAR file ${reporting.jasper.web.war} to the folder $LIFERAY_HOME/deploy when the portal is running. Note that the current integration of JasperReports version is 3.6.2. You will be able to upgrade it to the latest version of JasperReports anytime. The Reports portlets The plugin Reports Console defines two portlets: Reports Console at Control Panel and Reports Display. The portlet Reports Display is instanceable—that is, you can add more than one instance of the portlet on a page. You could bring the plugin Reports Console into the portal by following these steps: Download the WAR file ${reports.console.portlet.war} from http://liferay.cignex.com/palm_tree/book/0387/chapter12/reports-console-portlet-6.0.0.1.warr Drop the WAR file ${reports.console.portlet.war} to the folder$LIFERAY_HOME/deploy when the portal is running. As shown in the following screenshot, the portlet Reports Display provides the ability to search for reports and display search results with pagination. Search results will be displayed with a set of columns: Report Definition Name, Report Format, Requested Date, and Reporting Date. As you can see, you can search for reports via basic search or advanced search. The advanced search would cover the following items: Match All of the following fields: All or Any Definition Name: User's input Datasource Name: Jasper Empty, Portal Format: csv, excel, HTML, pdf, rtf, Text, and XML Requesting User Name:User's input Start date:A date End date:A date Active: Yes or No The portlet Reports Console provides the abilities to manage reports in the Control Panel. By going to Content | Reports Console under the Control Panel, you can search for generated reports under the tab Generated Reports. You can also create report definitions under the tab Report Definitions. Under the tab Report Definition, you would be able to search report definitions via basic search or advanced search. The advanced search would cover the following items: Match All of the following fields: All or Any Definition Name: User's input Description: User's input Datasource Name: Multiple checkboxes, Jasper Empty or Portal Of course, you could add definitions with the following items: Definition Name: Input required Description: User's input Datasource Name: Empty or Portal Template: Uploading template file (required) Report Parameters: Multiple pair (key, value) Key: User's input; optionally, it is bound to Report parameters Value: User's input Permissions: A checkbox—Public permissions configuration.
Read more
  • 0
  • 0
  • 4225

article-image-aggregate-services-servicemix-jbi-esb
Packt
22 Oct 2009
10 min read
Save for later

Aggregate Services in ServiceMix JBI ESB

Packt
22 Oct 2009
10 min read
EAI - The Broader Perspective No one should have (or will) ever dared to build a 'Single System' which will take care of the entire business requirements of an enterprise. Instead, we build few (or many) systems,and each of them takes care of a set of functionalities in a single Line of Business (LOB). There is absolutely nothing wrong here, but the need of the hour is that these systems have to exchange information and interoperate in many new ways which have not been foreseen earlier. Business grows, enterprise boundaries expands and mergers and acquisition are all norms of the day. If IT cannot scale up with these volatile environments, the failure is not far. Let me take a single, but not simple problem that today's Businesses and IT face - Duplicate Data. By Duplicate Data we mean data related to a single entity stored in multiple systems and storage mechanisms, that too in multiple formats and multiple content. I will take the 'Customer' entity as an example so that I can borrow the 'Single Customer View' (SCV) jargon to explain the problem. We gather customer information while he makes a web order entry or when he raises a complaint against the product or service purchased or when we raise a marketing campaign for a new product to be introduced or ... The list continues, and in each of these scenarios we make use of different systems to collect and store the same customer information. 'Same Customer' - is it same? Who can answer this question? Is there a Data Steward who can provide you with the SCV from amongst the many information silos existing in your Organization? To rephrase the question, does your organization at least have a 'Single View of Truth', if it doesn't have a 'Single Source of Truth'? Information locked away inside disparate, monolithic application silos has proven a stubborn obstacle in answering the queries business requires, impeding the opportunities of selling, not to mention cross-selling and up-selling. Yeah, it's time to cleanse and distill each customer's data into a single best-record view that can be used to improve source system data quality. For that, first we need to integrate the many source systems available. Today, companies are even acquiring just to get access to it's invaluable Customer information! This is just one of the highlights of the importance of integration to control Information Entropy in the otherwise complicated IT landscape. Figure 1. The 'Single Customer View' Dilemma So Integration is not an end, but a means to end a full list of problems faced by enterprises today. We have been doing integration for many years. There exist many platforms, technologies and frameworks doing the same thing. Built around that, we have multiple Integration Architectures too, amongst which, the Point to Pont, Hub and Spoke, and the Message Bus are common. Figure 2 represents these integration topologies. Figure 2. EAI Topologies Let us now look at the salient features of these topologies to see if we are self-sufficient or need something more. Point to Point In Point to Point, we define integration solutions for a pair of applications. Thus, we have two end points to be integrated. We can build protocol and/or format adaptors/transformers at one or either end. This is the easiest way to integrate, as long as the volume of integration is low. We normally use technology specific APIs like FTP, IIOP, Remoting or batch interfaces to realize integration. The advantage is that between these two points, we have tight coupling, since both ends have knowledge about their peers. The downside is that if there are 6 nodes (systems) to be interconnected, we need at least 30 separate channels for both forward and reverse transport. So think of a mid-sized Enterprise with some 1000 systems to integrate! Hub & Spoke Hub And Spoke Architecture is also called as the Message Broker. It provides a centralized hub (Broker) to which all applications are connected. Each application connects with the central hub through lightweight connectors. The lightweight connectors facilitate application integration with minimum or no changes to the existing applications. Message Transformation and Routing takes place within the Hub. The major drawback of the Hub and Spoke Architecture is that if the Hub fails, the entire Integration topology fails. Enterprise Message Bus An Enterprise Message Bus provides a common communication infrastructure which acts as a platform-neutral and language-neutral adaptor between applications. This communication infrastructure may include a Message Router and/or Publish-Subscribe channels. So applications interact each other through the message bus with the help of Request-Response queues. Sometimes the applications have to use adapters that handle scenarios like invoking CICS transactions. Such adapters may provide connectivity between the applications and the message bus using proprietary bus APIs and application APIs. Service Oriented Integration (SOI) Service Oriented Architecture (SOA) provides us with a set of principles, patterns and practices, to provide and consume services which are orchestrated using open standards so as to remove single vendor lock-into provide an agile infrastructure where services range from business definition to technical implementation. In SOA, we no longer deal with single format and single protocol, instead we accept the fact that heterogeneity exists between applications. And our architecture still needs to ensure interoperability and thus information exchange. To help us do integration in the SOA manner, we require a pluggable service infrastructure where providers, consumers, and middleware services can collaborate in the famous 'Publish -- Find -- Bind' triangle. So, similar to the integration topologies described above, we need a backbone upon which we can build SOA that can provide a collection of middleware services that provides integration capabilities. This is what we mean by Service Oriented Integration (SOI). Gartner originally identified Enterprise Service Bus (ESB) Architecture as a core component in the SOA landscape. ESB provides a technical framework to align your SOA based integration needs. In the rest of the article we will concentrate on ESB. Enterprise Service Bus (ESB) Roy Schutle from Gartner defines an ESB as:"A Web-services-capable middleware infrastructure that supports intelligent program-to-program communication and mediates the relationships among loosely-coupled and uncoupled business components." In the ESB Architecture (Refer Figure 2), applications communicate through an SOA middleware backbone. The most distinguishing feature of the ESB Architecture is the distributed nature of the integration topology. This makes the ESB capabilities to spread out across the bus in a distributed fashion, thus avoiding any single point of failure. Scalability is achieved by distributing the capabilities into separately deployable service containers. Smart, intelligent connectors connect the applications to the Bus. Technical services like transformation, routing, security, etc. are provided internally by these connectors. The Bus federates services which are hosted locally or remotely, thus collaborating distributed capabilities. Many ESB solutions are based on Web Services Description Language (WSDL) technologies, and they use Extensible Markup Language (XML) formats for message translation and transformation. The best way to think about an ESB is to imagine the many features which we can provide to the message exchange at a mediation layer (the ESB layer), a few among them is listed below: Addressing & Routing  Synchronous and Asynchronous style invocations  Multiple Transport and protocol bindings  Content transformation and translation  Business Process Orchestration (BPM)  Event processing  Adapters to multiple platforms  etc... Service Aggregation in ESB ESB provides you the best ways of integrating services so that services are not only interoperable but also reusable in the form of aggregating in multiple ways and scenarios. This means, services can be mixed and matched to adapt to multiple protocols and consumer requirements. Let me explain you this concept, as we will explore more into this with the help of sample code too. In code and component reuse, we try to reduce ‘copy and paste’ reuse and encourage inheritance, composition and instance pooling. Similar analogy exists in SOI where services are hosted and pooled for multiple clients through multiple transport channels, and ESB can do this in the best way integration world has ever seen. We call this as the notion of shared services. For example, if a financial organization provides a ‘credit history check service’, an ESB can facilitate reuse of this service by multiple business processes (like a Personal Loan approval process or a Home Mortgage approval process). So, once we create our 'core services', we can then arbitrarily compose these services in a declarative fashion so as to define and publish more and more composite services. Business Process Management (BPM) tools can be integrated over ESB to leverage service aggregation and service collaboration. This facilitates reuse of basic or core (or fine grained) services at Business Process level. So, granularity of services is important which will also decide the level of reusability. Coarse grained or composite services consume fine grained services. Applications that consume  coarse-grained services are not exposed to the fine-grained services they use. Composite services can be assembled from coarse-grained as well as fine-grained services. To make the concept clear, let us take the example of provisioning a new VOIP (Voice Over IP) Service for a new Customer. This is a composite service which in turn calls multiple coarse grained services like 'validateOrder', 'createOrVerifyCustomer', 'checkProductAvailability', etc. Now, the createOrVerifyCustomer coarse grained service in turn call multiple fine grained services like 'validateCustomer', 'createCustomer', 'createBillingAddress', 'createMailingAddress', etc. Figure 3. Service Composition Java Business Integration (JBI) Java Business Integration (JBI) provides a collaboration framework which provides standard interfaces for integration components and protocols to plug into, thus allowing the assembly of Service Oriented Integration (SOI) frameworks. JSR 208 is an extension of Java 2 Enterprise Edition (J2EE), but it is specific for Java Business Integration Service Provider Interfaces (SPI). SOA and SOI are the targets of JBI and hence it is built around Web Services Description Language (WSDL). The nerve of the JBI architecture is the NMR (Normalized Message Router). This is a bus through which messages flow in either directions from a source to a destination. You can listen to Ron Ten-Hove, the Co-spec lead for JSR 208 here and he writes more about JBI components in the PDF download titled JBI Components: Part 1. JBI provides the best available, open foundation for structuring applications by composition of services rather than modularized, structured code that we have been doing in traditional programming paradigms. A JBI compliant ESB implementation must support four different service invocations, leading to four corresponding Message Exchange Patterns (MEP):   One-Way (In-Only MEP): Service Consumer issues a request to Service Provider. No error (fault) path is provided.  Reliable One-Way (Robust In-Only MEP): Service Consumer issues a request to Service Provider. Provider may respond with a fault if it fails to process the request.  Request-Response (In-Out MEP): Service Consumer issues a request to Service Provider, with expectation of response. Provider may respond with a fault if it fails to process request.  Request Optional-Response (In Optional-Out MEP): Service Consumer issues a request to Service Provider, which may result in a response. Both Consumer and provider have the option of generating a fault in response to a message received during the interaction.
Read more
  • 0
  • 0
  • 4222
article-image-user-input-validation-tapestry-5
Packt
16 Oct 2009
9 min read
Save for later

User Input Validation in Tapestry 5

Packt
16 Oct 2009
9 min read
Adding Validation to Components The Start page of the web application Celebrity Collector has a login form that expects the user to enter some values into its two fields. But, what if the user didn't enter anything and still clicked on the Log In button? Currently, the application will decide that the credentials are wrong and the user will be redirected to the Registration page, and receive an invitation to register. This logic does make some sense; but, it isn't the best line of action, as the button might have been pressed by mistake. These two fields, User Name and Password, are actually mandatory, and if no value was entered into them, then it should be considered an error. All we need to do for this is to add a required validator to every field, as seen in the following code: <tr> <td> <t:label t_for="userName"> Label for the first text box</t:label>: </td> <td> <input type="text" t_id="userName" t_type="TextField" t:label="User Name" t_validate="required"/> </td></tr><tr> <td> <t:label t_for="password"> The second label</t:label>: </td><td> <input type="text" t_id="password" t_label="Password" t:type="PasswordField" t_validate="required"/></td></tr> Just one additional attribute for each component, and let's see how this works now. Run the application, leave both fields empty and click on the Log In button. Here is what you should see: Both fields, including their labels, are clearly marked now as an error. We even have some kind of graphical marker for the problematic fields. However, one thing is missing—a clear explanation of what exactly went wrong. To display such a message, one more component needs to be added to the page. Modify the page template, as done here: <t:form t_id="loginForm"> <t:errors/> <table> The Errors component is very simple, but one important thing to remember is that it should be placed inside of the Form component, which in turn, surrounds the validated components. Let's run the application again and try to submit an empty form. Now the result should look like this: This kind of feedback doesn't leave any space for doubt, does it? If you see that the error messages are strongly misplaced to the left, it means that an error in the default.css file that comes with Tapestry distribution still hasn't been fixed. To override the faulty style, define it in our application's styles.css file like this: DIV.t-error LI{ margin-left: 20px;} Do not forget to make the stylesheet available to the page. I hope you will agree that the efforts we had to make to get user input validated are close to zero. But let's see what Tapestry has done in response to them: Every form component has a ValidationTracker object associated with it. It is provided automatically, we do not need to care about it. Basically, ValidationTracker is the place where any validation problems, if they happen, are recorded. As soon as we use the t:validate attribute for a component in the form, Tapestry will assign to that component one or more validators, the number and type of them will depend on the value of the t:validate attribute (more about this later). As soon as a validator decides that the value entered associated with the component is not valid, it records an error in the ValidationTracker. Again, this happens automatically. If there are any errors recorded in ValidationTracker, Tapestry will redisplay the form, decorating the fields with erroneous input and their labels appropriately. If there is an Errors component in the form, it will automatically display error messages for all the errors in ValidationTracker. The error messages for standard validators are provided by Tapestry while the name of the component to be mentioned in the message is taken from its label. A lot of very useful functionality comes with the framework and works for us "out of the box", without any configuration or set-up! Tapestry comes with a set of validators that should be sufficient for most needs. Let's have a more detailed look at how to use them. Validators The following validators come with the current distribution of Tapestry 5: Required—checks if the value of the validated component is not null or an empty string. MinLength—checks if the string (the value of the validated component) is not shorter than the specified length. You will see how to pass the length parameter to this validator shortly. MaxLength—same as above, but checks if the string is not too long. Min—ensures that the numeric value of the validated component is not less than the specified value, passed to the validator as a parameter. Max—as above, but ensures that the value does not exceed the specified limit. Regexp—checks if the string value fits the specified pattern. We can use several validators for one component. Let's see how all this works together. First of all, let's add another component to the Registration page template: <tr> <td><t:label t_for="age"/>:</td> <td><input type="text" t_type="textfield" t_id="age"/></td></tr> Also, add the corresponding property to the Registration page class, age, of type double. It could be an int indeed, but I want to show that the Min and Max validators can work with fractional numbers too. Besides, someone might decide to enter their age as 23.4567. This will be weird, but not against the laws. Finally, add an Errors component to the form at the Registration page, so that we can see error messages: <t:form t_id="registrationForm"> <t:errors/> <table> Now we can test all the available validators on one page. Let's specify the validation rules first: Both User Name and Password are required. Also, they should not be shorter than three characters and not longer than eight characters. Age is required, and it should not be less than five (change this number if you've got a prodigy in your family) and not more than 120 (as that would probably be a mistake). Email address is not required, but if entered, should match a common pattern. Here are the changes to the Registration page template that will implement the specified validation rules: <td> <input type="text" t_type="textfield" t_id="userName" t:validate="required,minlength=3,maxlength=8"/></td>...<td> <input type="text" t_type="passwordfield" t_id="password" t:validate="required,minlength=3,maxlength=8"/></td>...<td> <input type="text" t_type="textfield" t_id="age" t:validate="required,min=5,max=120"/></td>...<input type="text" t_type="textfield" t_id="email" t:validate="regexp"/> As you see, it is very easy to pass a parameter to a validator, like min=5 or maxlength=8. But, where do we specify a pattern for the Regexp validator? The answer is, in the message catalog. Let's add the following line to the app.properties file: email-regexp=^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$ This will serve as a regular expression for all Regexp validators applied to components with ID email throughout the application. Run the application, go to the Registration page and, try to submit the empty form. Here is what you should see: Looks all right, but the message for the age could be more sensible, something like You are too young! You should be at least 5 years old. We'll deal with this later. However for now, enter a very long username, only two characters for password and an age that is more than the upper limit, and see how the messages will change: Again, looks good, except for the message about age. Next, enter some valid values for User Name, Password and Age. Then click on the check box to subscribe to the newsletter. In the text box for email, enter some invalid value and click on Submit. Here is the result: Yes! The validation worked properly, but the error message is absolutely unacceptable. Let's deal with this, but first make sure that any valid email address will pass the validation.   Providing Custom Error Messages We can provide custom messages for validators in the application's (or page's) message catalog. For such messages we use keys that are made of the validated component's ID, the name of validator and the "message" postfix. Here is an example of what we could add to the app.properties file to change error messages for the Min and Max validators of the Age component as well as the message used for the email validation: email-regexp-message=Email address is not valid.age-min-message=You are too young! You should be at least 5 years old.age-max-message=People do not live that long! Still better, instead of hard-coding the required minimal age into the message, we could insert into the message the parameter that was passed to the Min validator (following the rules for java.text.Format), like this: age-min-message=You are too young! You should be at least %s years old. If you run the application now and submit an invalid value for age, the error message will be much better: You might want to make sure that the other error messages have changed too. We can now successfully validate values entered into separate fields, but what if the validity of the input depends on how two or more different values relate to each other? For example, at the Registration page we want two versions of password to be the same, and if they are not, this should be considered as an invalid input and reported appropriately. Before dealing with this problem however, we need to look more thoroughly at different events generated by the Form component.  
Read more
  • 0
  • 0
  • 4197

article-image-financial-management-microsoft-dynamics-ax-2012-r3
Packt
11 Feb 2015
4 min read
Save for later

Financial Management with Microsoft Dynamics AX 2012 R3

Packt
11 Feb 2015
4 min read
In this article by Mohamed Aamer, author of Microsoft Dynamics AX 2012 R3 Financial Management, we will cover that the core foundation of Enterprise Resource Planning (ERP) is financial management; it is vital to comprehend the financial characteristics in Microsoft Dynamics AX 2012 R3 from a practical perspective engaged with the application mechanism. It is important to cover the following topics: Understanding financial management aspects in Microsoft Dynamics AX 2012 R3 Covering the business rational, basic setups, and configuration Real-life business requirements and its solution Hints of implementation tips and tricks in addition to the key consideration points during analysis, design, deployment, and operation (For more resources related to this topic, see here.) Microsoft Dynamics AX 2012 R3 Financial Management book covers the main characteristics general ledger and its integration between other subledgers (Accounts payable, Accounts receivable, fixed assets, cash and bank management, and inventory). It also covers the core features of main accounts, the categorization accounts, and its controls, along with the opening balance process and concept, and the closing procedure. It then discusses subledgers functionality (Accounts payable, Accounts receivable, fixed assets, cash and bank management, cash flow management, and inventory) in more details by walking through the master data, controls, and transactions and its effects on the general ledger. It explores financial reporting that is one of the basic implementation corner stone. The main principles for reporting are reliability of business information and the ability to get the right information at the right time for the right person. Reports that analyze ERP data in an expressive way represent the output of the ERP implementation; it is considered as the cream of the implementation—the next level of value that solution stakeholders should target for. This ultimate outcome results from building all reports based on a single point of information. Planning reporting needs for ERP The Microsoft Dynamics AX implementation teamwork should challenge the management's reporting needs in the analysis phase of the implementation with a particular focus on exploring the data required to build reports. These data requirements should then be cross-checked with the real data entry activities that end users will execute to ensure that business users will get vital information from the reports. The reporting levels are as follows: Operational management Middle management Top management Understanding information technology value chain The model of a management information system is most applicable to the Information Technology (IT) manager or Chief Information Officer (CIO) of a business. Business owners likely don't care as much about the specifics as long as these aspects of the solution deliver the required results. The following are the basic layers of the value chain: Database management Business processes Business Intelligence Frontend Understanding Microsoft Dynamics AX information source blocks This section explores the information sources that eventually determine the strategic value of Business Intelligence (BI) reporting and analytics. These are divided into three blocks. Detailed transactions block Business Intelligence block Executive decisions block Discovering Microsoft Dynamics AX reporting The reporting options offered by Microsoft Dynamics AX are: Inquiry forms SQL Reporting Services (SSRS) reports The original transaction The Original document function Audit trail Reporting currency Companies report their transactions in a specific currency that is known as accounting currency or local currency. It is normal to post transactions in a different currency, and this amount of money is translated to the home currency using the current exchange rate. Autoreports The Autoreport wizard is a user-friendly tool. The end user can easily generate a report starting from every form in Microsoft Dynamics AX. This wizard helps the user to create a report based on the information in the form and save the report. Summary In this article, we covered financial reporting from planning to consideration of reporting levels. We covered important points that affect reporting quality by considering the reporting value chain, which consists of infrastructure, database management, business processes, business intelligence, and the frontend. We also discussed the information source blocks, which consist of the detailed transactions block, business intelligence block, and executive decisions block. Then we learned about the reporting possibilities in Microsoft Dynamics AX such as inquiry forms and SSRS reports, and autoreport capabilities in Microsoft Dynamics AX 2012 R3. Resources for Article: Further resources on this subject: Customization in Microsoft Dynamics CRM [Article] Getting Started with Microsoft Dynamics CRM 2013 Marketing [Article] SOP Module Setup in Microsoft Dynamics GP [Article]
Read more
  • 0
  • 0
  • 4187

article-image-apache-felix-gogo
Packt
10 Nov 2010
10 min read
Save for later

Apache Felix Gogo

Packt
10 Nov 2010
10 min read
  OSGi and Apache Felix 3.0 Beginner's Guide Build your very own OSGi applications using the flexible and powerful Felix Framework Build a completely operational real-life application composed of multiple bundles and a web front end using Felix Get yourself acquainted with the OSGi concepts, in an easy-to-follow progressive manner Learn everything needed about the Felix Framework and get familiar with Gogo, its command-line shell to start developing your OSGi applications Simplify your OSGi development experience by learning about Felix iPOJO A relentlessly practical beginner's guide that will walk you through making real-life OSGi applications while showing you the development tools (Maven, Eclipse, and so on) that will make the journey more enjoyable The Tiny Shell Language The command syntax for the shell interface is based on the Tiny Shell Language (TSL) . It is simple enough to allow a lightweight implementation, yet provides features such as pipes, closures, variable setting and referencing, collection types such as lists and maps, and so on. The TSL syntax allows the creation of scripts that can be executed by the shell runtime service. The introduction you will get here does not cover the complete syntax; instead, you will see the basic parts of it. For a review of the proposal in its initial state, (http://www.osgi.org/download/osgi-4.2-early-draft.pdf). You may also refer to the RFC 147 Overview on the Felix documentation pages (http://felix.apache.org/site/rfc-147-overview.html) for potential differences with the initial draft . Chained execution A program is a set of chained execution blocks. Blocks are executed in parallel, and the output of a block is streamed as input to the next. Blocks are separated by the pipe character ( | ). Each block is made up of a sequence of statements, separated by a semicolon ( ; ). For example, as we'll see in the next section, the bundles command lists the currently installed bundles and the grep command takes a parameter that it uses to filter the input. The program below: bundles | grep gogo is made of two statement blocks, namely, bundles and grep gogo. The output of the bundles statement will be connected to the input of the grep gogo statement (here each the statement block contains one statement). Running this program on your Felix installation, in the state it is now, will produce: g! bundles | grep gogo 2|Active | 1|org.apache.felix.gogo.command (0.6.0) 3|Active | 1|org.apache.felix.gogo.runtime (0.6.0) 4|Active | 1|org.apache.felix.gogo.shell (0.6.0) true The grep statement has filtered the output of the bundles statement for lines containing the filter string gogo. In this case, the grep statement outputs the results of its execution to the shell which prints it. Executing the statement grep gogo on its own, without a piped block that feeds it input, will connect its input to the user command line. In that case, use Ctrl-Z to terminate your input: g! grep gogo line 1 line 2 gogo line 2 gogo line 3 ^Z true Notice that line 2 gogo is repeated right after you have entered it, showing that the grep statement is running in parallel. It receives the input and processes it right after you enter it. Variable assignment and referencing A session variable is assigned a value using the equal character ( = ) and referenced using its name preceded with a dollar character ( $ ). For example: g! var1 = 'this is a string' this is a string g! echo $var1 this is a string The assignment operation returns the assigned value. Value types We've seen the string type previously, which is indicated by surrounding text with single quotes ( ' ). A list is a sequence of terms separated by whitespace characters and is delimited by an opening and a closing square bracket. For example: g! days = [ mon tue wed thu fri sat sun ] mon tue wed thu fri sat sun Here the variable, days, was created, assigned the list as a value, and stored in the session. A map is a list of assignments, the value is assigned to the key using the equal character ( = ) . For example: For example: g! sounds = [ dog=bark cat=meow lion=roar ] dog bark cat meow lion roar Here, the variable sounds is assigned a map with the preceding key value pairs. Object properties and operations The shell uses a mapping process that involves reflection to find the best operation to perform for a request. We're not going to go into the details of how this happens; instead, we'll give a few examples of the operations that can be performed. We'll see a few others as we go along. In the same session, days and sounds are defined previously to retrieve an entry in the $days list: g! $days get 1 tue To retrieve an entry in the sounds map g! $sounds get dog bark An example we've seen earlier is the bundles command used when illustrating the piping. Bundles was mapped to the method getBundles() from the Gogo Runtime bundle BundleContext instance. Another property of this object that we'll use in the next section is bundle &ltid> to get a bundle object instance using getBundle(long). Execution quotes Similar to the UNIX back-quote syntax, but providing one that's simpler for a lightweight parser, the execution quotes are used to return the output of an executed program. For example: g!(bundle 1) location file:/C:/felix/bundle/org.apache.felix.bundlerepository-1.6.2.jar Here, (bundle 1) has returned the bundle with ID 1, which we've re-used to retrieve the property location making use of Gogo's reflexion on beans (location is mapped to getLocation() on the Bundle object ). Commands and scopes The Gogo Runti me command processor is extensible and allows any bundle to register the commands it needs to expose to the user. Then, when the user types a command, the processor will attempt to find the method that's best fit to be executed, based on the command name and passed arguments. However, there are potential cases where two bundles would need to register the same command name. To avoid this clash, commands are registered with an opti onal scope. When there is no ambiguity as to which scope the command belongs to, the command can be used without a scope; otherwise, the scope must be included. The scope of a command is specified by pre-pending it to the command, separated from the command with a colon ( : ). In the previous examples, we've used the grep command, which is in the gogo scope. In this case, grep and gogo:grep achieve the same result. We will look closer at the command registration mechanism. Let's take a tour of some of the commands available in the Felix distribution. At the time of writing of this article, the Gogo bundles are at version 0.6.0, which means that they are not yet finalized and may change by the time they are released with version 1.0. felix scope commands One of the many powerful features of Felix (and OSGi-compliant applications in general) is that many actions can be applied on bundles without needing to restart the framework. Bundles can be installed, updated, uninstalled, and so on while the remaining functionality of the framework is active. The following are some of the available commands and a description of their usage. We will get to use many of those as we go along, so you need not worry much about learning them by heart. Just know they exist. Listing installed bundles: lb One of the most frequently used shell commands is the list bundles command (lb) , which gives a listing of the currently installed bundles, showing some informationon each of them. Let's check what's running on our newly installed framework: g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.1) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) 2|Active | 1|Apache Felix Gogo Command (0.6.0) 3|Active | 1|Apache Felix Gogo Runtime (0.6.0) 4|Active | 1|Apache Felix Gogo Shell (0.6.0) The listing provides the following useful information about each bundle: Each bundle is given a unique id on install—this ID is used by commands such as update or uninstall to apply acti ons on that bundle The bundle's start level The bundle's name and version This command also takes a parameter for filtering the bundles list. For example, to include only bundles that have 'bundle' in their name: g! lb bundle START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.1) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) help The help command provides hints on the usage of commands. When called without any parameters, the help command gives a listing of the available commands: g! help felix:bundlelevel felix:cd felix:frameworklevel felix:headers felix:help felix:inspect felix:install felix:lb felix:log felix:ls felix:refresh felix:resolve felix:start felix:stop felix:uninstall felix:update felix:which gogo:cat gogo:each gogo:echo gogo:format gogo:getopt gogo:gosh gogo:grep gogo:not gogo:set gogo:sh gogo:source gogo:tac gogo:telnetd gogo:type gogo:until obr:deploy obr:info obr:javadoc obr:list obr:repos obr:source More help on the syntax of each command can be requested by typing help &ltcommand-name>. For example, for more help on the repos command: g! help repos repos - manage repositories scope: obr parameters: String ( add | list | refresh | remove ) String[] space-delimited list of repository URL When the command is available with multiple signatures, a help block per signature is provided, for example: g! help help help - displays information about a specific command scope: felix parameters: String target command help - displays available commands scope: felix Here, the help command has 2 syntaxes: one that takes a parameter (the target command), and another that takes no parameters. We've used the first one to get help on help. Some commands may have not registered help content with the shell service. Those will show minimal information using help &ltcommand>. In most cases, they expose a separate help listing—usually &ltcommand> -? or &ltcommand> -- help. install The install command is used to instruct Felix to install an external bundle. The syntax is as follows: g! help install install - install bundle using URLs scope: felix parameters: String[] target URLs Each bundle is located using the URL and is downloaded to the local cache for installation. Once a bundle is installed, it is given a unique id. This ID is used to refer to this bundle when using commands such as update or uninstall. For example: g! install http://www.mysite.com/testbundle-1.0.0.jar Bundle ID: 7 Here, the bundle I've just installed has the ID 7. g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 0|System Bundle (3.0.1) 1|Active | 1|Apache Felix Bundle Repository (1.6.2) 2|Active | 1|Apache Felix Gogo Command (0.6.0) 3|Active | 1|Apache Felix Gogo Runtime (0.6.0) 4|Active | 1|Apache Felix Gogo Shell (0.6.0) 7|Installed | 1|Test Bundle (1.0.0) In cases where many bundles are to be installed from the same base URL, you may want to set a session variable with the common base URL to simplify the task. For example, instead of executing: g! install http://site.com/bundle1.jar http://site.com/bundle2.jar You would write: g! b = http://site.com g! install $b/bundle1.jar $b/bundle2.jar
Read more
  • 0
  • 0
  • 4183
article-image-visual-basic-applications-vba
Packt
31 Dec 2012
5 min read
Save for later

Visual Basic for Applications (VBA)

Packt
31 Dec 2012
5 min read
(For more resources related to this topic, see here.) What kind of things can you do with it? Once you have pushed your experience using the Office application to the limits and you can no longer get your job done due to a lack of built-in tools, using VBA will help avert frustrations you may encounter along the way. VBA enables you to build custom functions, also called User-defined Functions (UDFs), and you can automate tedious tasks such as defining and cleaning formats, manipulate system objects such as files and folders, as well as work together with Windows as a combined system, through its Application Programming Interface (API), and other applications by referencing their object libraries or Dynamic-link Libraries (DLLs). Of course you can also use VBA to manipulate the Office application that hosts your code. For example, you can customize the user interface in order to facilitate the work you and others do. An important thing to remember, though, is that the VBA code that you create is used within the host application. In our case, the code will run within Excel. Such VBA programs are not standalone, that is, they cannot run by themselves; they need the host application in order to operate correctly. How can you use this technology within your existing projects? You can use VBA in two different ways. The first, and most common way is to code directly into your VBA project. For example, you may have an Excel workbook with some custom functions that calculate commissions. You can add modules to this workbook and code the UDFs in this module. Another option would be to save the workbook as an Addin. An Addin is a specialized document that hosts the code and makes it available to other workbooks. This is very useful when you need to share the solutions you develop with other workbooks and co-workers. Recording a macro, adding modules, browsing objects, and variables Before you get your hands "dirty" with coding in VBA, there are a few things you need to know. These things will help when it comes to coding. In this section, you will learn how to: Record a macro Add modules Browse objects Get some background on declaring variables We will start with macro recording, a feature which is available in most Office applications. Recording a macro A macro, in Office applications, is a synonym for VBA code. In Excel, we can record almost any action we perform (such as mouse clicks and typing), which in turn is registered as VBA code. This can come in handy when we need to discover properties and methods related to an object. Let us now have a look at some ways you can record a macro in Excel. There are two options: Recording a macro from the status bar. Recording from the Developer tab. Option 1 — Recording a macro from the status bar From the status bar, click on the Record Macro button. If the button is not visible, right-click on the status bar and from the pop-up menu, choose the Macro Recording option, as shown in the following screenshot: Option 2 — Recording from the Developer tab Now that you know how to record a macro from the status bar, let us check another option. This option requires that you activate the Developer tab. In order to activate it, assuming it is not active yet, follow these steps: Go to File | Excel Options | Customize Ribbon. Under Main Tabs check the Developer checkbox, as shown in the following screenshot : Next, activate the Developer tab and click on Record Macro, as shown in the following screenshot: Once the macro recording process starts, you will be prompted to enter some basic information about the macro such as the macro name, the shortcut key, location where the macro should be stored, and its description. The following screenshot shows these options filled out: Once the macro has been recorded, you can access its container module by pressing, simultaneously, the Alt + F11 keys. Alternatively, you can click on the Visual Basic button in the Developer tab. This button is to the left of the Record Macro button introduced previously. This will open the Visual Basic Editor (VBE), where all the VBA code is kept. The VBE is the tool we use to create, modify, and maintain any code we write or record. The following screenshot shows the VBE window with the project explorer, properties, and code window visible: If upon opening the VBE, the VBA project explorer window is not visible, then follow these steps: Go to View | Project Explorer. Alternatively, press the Ctrl + R keys simultaneously. If, on the other hand, the VBA project explorer is visible, but the code window is not, you can choose which code window to show. Suppose you are interested in the content of the module you've recorded from the project explorer window, follow these step to show the module window: Click on View | Code. Alternatively, press F7. Summary In this article, you have learned some basic stuff about VBA. These included macro recording, adding modules, and browsing objects. Resources for Article : Further resources on this subject: Understanding ShapeSheet™ in Microsoft Visio 2010 [Article] Excel 2010 Financials: Using Graphs for Analysis [Article] Excel 2010 Financials: Adding Animations to Excel Graphs [Article]
Read more
  • 0
  • 0
  • 4168

article-image-planning-and-preparing-oracle-siebel-crm-installation
Packt
10 Aug 2010
5 min read
Save for later

Planning and Preparing the Oracle Siebel CRM Installation

Packt
10 Aug 2010
5 min read
(For more resources on Oracle, see here.) The overall process of planning and preparation can be described as follows. The following flowchart describes the major steps of the process of planning and preparing a Siebel CRM installation. In this article, we will describe each step in detail. Planning the Siebel CRM installation Implementing Siebel CRM for thousands of users in corporations that do business across the globe is not something a single person would do on a single day. Sometimes, hundreds of technicians, IT architects and business analysts are involved to fulfil the company's requirements. Siebel CRM projects can be costly, lengthy, and sometimes risky expeditions into rough terrain. In a typical Siebel CRM project, people from various companies—integrators and IT staff of the customer—work together to install and set up the different Siebel environments from first prototyping areas over the development, test, and training environments, to the final production environment. Siebel and third-party software for these environments are typically installed on multiple server machines and it is not unusual to find a mix of operating systems. What is expected from us—being the reliable and trustworthy expert that the customer hired to install Siebel CRM on their systems—is a planning document. The key to a useful planning document is knowledge about the customer's IT infrastructure, as well as the Siebel installation and configuration processes. The following is an example of a typical planning document that provides all the information that is needed to successfully install the Siebel CRM infrastructure on Microsoft Windows machines. The official Siebel Installation Guide includes a Deployment Planning Worksheet, which can serve as a starting point. In a real life project, we can use any spreadsheet application to create and collaborate on this information. Sample planning document The following table is a sample planning document for information regarding the relational database management system (RDBMS) to host the Siebel database. We record information about the RDBMS vendor and version as well as the machine hostname and administrative user account. For a typical Siebel CRM installation, we also plan the creation of two tablespaces. Details on how to create tablespaces and undertake other prerequisite installation steps are described later in this article. Component/Parameter Name/Value Examples Description Database Server Vendor Oracle   Database Server Version 11gR1   DB Server System Account/Password sys/T67PBhtr as SYSDBA Needed to connect directly to the database to run the grantusr.sql script. Database Server hostname dbsrvr1   DB host admin user Administrator   DB host admin user password XBXfi8F9 See the note on password examples. Database Server port 1521   Database Server SID ORCL   Siebel DB index tablespace SIEBELDB_IDX This tablespace will hold the indexes of the Siebel CRM schema. Siebel DB data tablespace SIEBELDB_DATA This tablespace will hold the data tables of the Siebel CRM schema. More planning information Of course, a decent planning document contains more than just a series of tables. Sometimes, we might need to bring specialists on board to define the necessary amount of servers, the hardware configuration, and so forth. Security-related information such as user accounts, remote access settings, or simply the phone numbers of the firewall administrators, can help the project team to finish a Siebel CRM infrastructure provisioning on time. Certainly, the project plan will include a timeline. We will not go into details of project management, but we should ensure that our project plan provides enough time and money for training—for both technicians and the end user community. Understanding hardware and software prerequisites Many problems in Siebel CRM projects arise from improper planning. As we learned, delivering a decent planning document is a key milestone of our Siebel CRM implementation project. Therefore, it is very important that any person involved in planning and conducting a Siebel CRM installation has access to the Siebel System Requirements and Supported Platforms document that can be downloaded from the Oracle Technology Network website: http://download.oracle.com/docs/cd/E11886_01/srsphomepage.html. This document is available for each individual Siebel CRM version and outlines in detail the minimum hardware requirements and software prerequisites. For example, if we plan to provide a prototype environment for evaluation and testing of Siebel CRM 8.1 and would like to use Microsoft Windows Server 2003 as the operating system, we would have to provision hardware and software as follows: Siebel Component Minimum Processor Requirements Minimum Memory Requirements Siebel Server 2 PIII XEON 500 MHz 1 GB Siebel Gateway Name Server PIII XEON 500 MHz 256 MB Web Server PIII XEON 500 MHz 512 MB If we were to install these components on a single piece of hardware, we would have to provision a 4 CPU unit (2 for the Siebel Server, 1 for the Siebel Gateway Name Server, and 1 for the Web Server) with at least 1.7 GB (1 GB plus 256 MB + 512 MB) of free memory for the Siebel components, which would be a physical minimum of 2 GB of memory as the operating system will also be hungry for memory. Sizing the Siebel deployment Installing Siebel CRM for personal evaluation or prototyping is one thing, providing a stable and high performing enterprise application to hundreds or thousands of end users is quite another challenge. In certain phases of the Siebel CRM implementation project, consultants and IT staff will have to deliver a sizing document that provides insight into the expected number of end users and their concurrent sessions. The necessary amount of hardware units and software components is dependent on these main factors: Maximum number of concurrent user sessions Expected volume of data and indexes Hardware vendor Operating system type Database vendor Network bandwidth High-availability and failover requirements Each of these has to be considered and evaluated. Customers typically rely on the services of experienced staff from either Oracle or consulting corporations to accomplish this.
Read more
  • 0
  • 0
  • 4166
Modal Close icon
Modal Close icon