Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
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

7019 Articles
article-image-integrating-websphere-extreme-scale-data-grid-relational-database-part-1
Packt
18 Nov 2009
10 min read
Save for later

Integrating Websphere eXtreme Scale Data Grid with Relational Database: Part 1

Packt
18 Nov 2009
10 min read
As stated above there are three compelling reasons to integrate with a database backend. First, reporting tools do not have good data grid integration. Using CrystalReports and other reporting tools, don't work with data grids right now. Loading data from a data grid into a data warehouse with existing tools isn't possible either. The second reason we want to use a database with a data grid is when we have an extremely large data set. A data grid stores data in memory. Though much cheaper than in the past, system memory is still much more expensive than a typical magnetic hard disk. When dealing with extremely large data sets, we want to structure our data so that the most frequently used data is in the cache and less frequently used data is on the disk. The third compelling reason to use a database with a data grid is that our application may need to work with legacy applications that have been using relational databases for years. Our application may need to provide more data to them, or operate on data already in the legacy database in order to stay ahead of a processing load.In this article, we will explore some of the good and not-so-good uses of an in-memory data grid. We'll also look at integrating Websphere eXtreme Scale with relational databases. You're going where? Somewhere along the way, we all learned that software consists of algorithms and data. CPUs load instructions from our compiled algorithms, and those instructions operate on bits representing our data. The closer our data lives to the CPU, the faster our algorithm can use it. On the x86 CPU, the registers are the closest we can store data to the instructions executed by the CPU. CPU registers are also the smallest and most expensive data storage location. The amount of data storable in registers is fixed because the number and size of CPU registers is fixed. Typically, we don't directly interact with registers because their correct usage is important to our application performance. We let the compiler writers handle translating our algorithms into machine code. The machine code knows better than we do, and will use register storage far more effectively than we will most of the time. Less expensive, and about an order of magnitude slower, we have the Level 1 cache on a CPU (see below). The Level 1 cache holds significantly more data than the combined storage capacity of the CPU registers. Reading data from the Level 1 cache, and copying it to a register, is still very fast. The Level 1 cache on my laptop has two 32K instruction caches, and two 32K data caches. Still less expensive, and another order of magnitude slower, is the Level 2 cache. The Level 2 cache is typically much larger than Level 1 cache. I have 4MB of the Level 2 cache on my laptop. It still won't fit the contents of the Library of Congress into that 4MB, but that 4MB isn't a bad amount of data to keep near the CPU. Up another level, we come to the main system memory. Consumer level PCs come with 4GB RAM. A low-end server won't have any less than 8GB. At this point, we can safely store a large chunk of data, if not all of the data, used by an application. Once the application exits, its data is unloaded from the main memory, and all of the data is lost. In fact, once our data is evicted from any storage at or below this level, it is lost. Our data is ephemeral unless it is put onto some secondary storage. The unit of measurement for accessing data in a register, either Level 1 or 2 cache and main memory, is a nanosecond. Getting to secondary storage, we jump up an SI-prefix to a microsecond. Accessing data in the secondary storage cache is on the order of microseconds. If the data is not in cache, the access time is on the order of milliseconds. Accessing data on a hard drive platter is one million times slower than accessing that same data in main memory, and one billion times slower than accessing that data in a register. However, secondary storage is very cheap and holds millions of times more than primary storage. Data stored in secondary storage is durable. It doesn't disappear when the computer is reset after a crash. Our operation teams comfortably build secondary storage silos to store petabytes of data. We typically build our applications so the application server interacts with some relational database management system that sits in front of that storage silo. The network hop to communicate with the RDBMS is in the order of microseconds on a fast network, and milliseconds otherwise. Sharing data between applications has been done with the disk + network + database approach for a long time. It's become the traditional way to build applications. Load balancer in front, application servers or batch processes constantly communicating with a database to store data for the next process that needs it. As we see with computer architecture, we insert data where it fits. We squeeze it as close to the CPU as possible for better performance. If a data segment doesn't fit in one level, keep squeezing what fits into each higher storage level. That leaves us with a lot of unused memory and disk space in an application deployment. Storing data in the memory is preferable to storing it on a hard drive. Memory segmentation in a deployment has made it difficult to store useful amounts of data at a few milliseconds distance. We just use a massive, but slow, database instead. Where does an IMDG fit? We've used ObjectGrid to store all of our data so far. This diagram should look pretty familiar by now: Because we're only using the ObjectGrid APIs, our data is stored in-memory. It is not persisted to disk. If our ObjectGrid servers crash, then our data is in jeopardy (we haven't covered replication yet). One way to get our data into a persistent store is to mark up our classes with some ORM framework like JPA. We can use the JPA API to persist, update, and remove our objects from a database after we perform the same operations on them using the ObjectMap or Entity APIs. The onus is on the application developer to keep both cache and database in sync: If you take this approach, then all of the effort would be for naught. Websphere eXtreme Scale provides functionality to integrate with an ORM framework, or any data store, through Loaders. A Loader is a BackingMap plugin that tells ObjectGrid how to transform an object into the desired output form. Typically, we'll use a Loader with an ORM specification like JPA. Websphere eXtreme Scale comes with a few different Loaders out of the box, but we can always write our own. A Loader works in the background, transforming operations on objects into some output, whether it's file output or SQL queries. A Loader plugs into a BackingMap in an ObjectGrid server instance, or in a local ObjectGrid instance. A Loader does not plug into a client-side BackingMap, though we can override Loader settings on a client-side BackingMap. While the Loader runs in the background, we interact with an ObjectGrid instance. We use the ObjectMap API for objects with zero or simple relationships, and the Entity API for objects with more complex relationships. The Loader handles all of the details in transforming an object into something that can integrate with external data stores: Why is storing our data in a database so important? Haven't we seen how much faster Websphere eXtreme Scale is than an RDBMS? Shouldn't all of our data be stored in in-memory? An in-memory data grid is good for certain things. There are plenty of things that a traditional RDBMS is good at that any IMDG just doesn't support. An obvious issue is that memory is significantly more expensive than hard drives. 8GB of server grade memory costs thousands of dollars. 8GB of server grade disk space costs pennies. Even though the disk is slower than memory, we can store a lot more data on it. An IMDG shines where a sizeable portion of frequently-changing data can be cached so that all clients see the same data. The IMDG provides orders of magnitude with better latency, read, and write speeds than any RDBMS. But we need to be aware that, for large data sets, an entire data set may not fit in a typical IMDG. If we focus on the frequently-changing data that must be available to all clients, then using the IMDG makes sense. Imagine a deployment with 10 servers, each with 64GB of memory. Let's say that of the 64GB, we can use 50GB for ObjectGrid. For a 1TB data set, we can store 50% of it in cache. That's great! As the data set grows to 5TB, we can fit 10% in cache. That's not as good as 50%, but if it is the 10% of the data that is accessed most frequently, then we come out ahead. If that 10% of data has a lot of writes to it, then we come out ahead. Websphere eXtreme Scale gives us predictable, dynamic, and linear scalability. When our data set grows to 100TB, and the IMDG holds only 0.5% of the total data set, we can add more nodes to the IMDG and increase the total percentage of cacheable data (see below). It's important to note that this predictable scalability is immensely valuable. Predictable scalability makes capacity planning easier. It makes hardware procurement easier because you know what you need. Linear scalability provides a graceful way to grow a deployment as usage and data grow. You can rest easy knowing the limits of your application when it's using an IMDG. The IMDG also acts as a shock absorber in front of a database. We're going to explore some of the reasons why an IMDG makes a good shock absorber with the Loader functionality. There are plenty of other situations, some that we have already covered, where an IMDG is the correct tool for the job. There are also plenty of situations where an IMDG just doesn't fit. A traditional RDBMS has thousands of man-years of research, implementation tuning, and bug fixing already put into it. An RDBMS is well-understood and is easy to use in application development. There are standard APIs for interacting with them in almost any language: In-memory data grids don't have the supporting tools built around them that RDBMSs have. We can't plug CrystalReports into an ObjectGrid instance to get daily reports out of the data in the grid. Querying the grid is useful when we run simple queries, but fails when we need to run the query over the entire data set, or run a complex query. The query engine in Websphere eXtreme Scale is not as sophisticated as the query engine in an RDBMS. This also means the data we get from ad hoc queries is limited. Running ad hoc queries in the first place is more difficult. Even building an ad hoc query runner that interacts with an IMDG is of limited usefulness. An RDBMS is a wonderful cross-platform data store. Websphere eXtreme Scale is written in Java and only deals with Java objects. A simple way for an organization to share data between applications is in a plaintext database. We have standard APIs for database access in nearly every programming language. As long as we use the supported database driver and API, we will get the results as we expect, including ORM frameworks from other platforms like .NET and Rails. We could go on and on about why an RDBMS needs to be in place, but I think the point is clear. It's something we still need to make our software as useful as possible.
Read more
  • 0
  • 0
  • 2157

article-image-unity-game-development-interactions-part-1
Packt
18 Nov 2009
8 min read
Save for later

Unity Game Development: Interactions (Part 1)

Packt
18 Nov 2009
8 min read
To detect physical interactions between game objects, the most common method is to use a Collider component—an invisible net that surrounds an object's shape and is in charge of detecting collisions with other objects. The act of detecting and retrieving information from these collisions is known as collision detection. Not only can we detect when two colliders interact, but we can also pre-empt a collision and perform many other useful tasks by utilizing a technique called Ray Casting, which draws a Ray—put simply, an invisible (non-rendered) vector line between two points in 3D space—which can also be used to detect an intersection with a game object's collider. Ray casting can also be used to retrieve lots of other useful information such as the length of the ray (therefore—distance), and the point of impact of the end of the line. In the given example, a ray facing the forward direction from our character is demonstrated. In addition to the direction, a ray can also be given a specific length, or allowed to cast until it finds an object. Over the course of the article, we will work with the outpost model. Because this asset has been animated for us, the animation of the outpost's door opening and closing is ready to be triggered—once the model is placed into our scene. This can be done with either collision detection or ray casting, and we will explore what you will need to do to implement either approach. Let's begin by looking at collision detection and when it may be appropriate to use ray casting instead of, or in complement to, collision detection. Exploring collisions When objects collide in any game engine, information about the collision event becomes available. By recording a variety of information upon the moment of impact, the game engine can respond in a realistic manner. For example, in a game involving physics, if an object falls to the ground from a height, then the engine needs to know which part of the object hit the ground first. With that information, it can correctly and realistically control the object's reaction to the impact. Of course, Unity handles these kinds of collisions and stores the information on your behalf, and you only have to retrieve it in order to do something with it. In the example of opening a door, we would need to detect collisions between the player character's collider and a collider on or near the door. It would make little sense to detect collisions elsewhere, as we would likely need to trigger the animation of the door when the player is near enough to walk through it, or to expect it to open for them. As a result, we would check for collisions between the player character's collider and the door's collider. However, we would need to extend the depth of the door's collider so that the player character's collider did not need to be pressed up against the door in order to trigger a collision, as shown in the following illustration. However, the problem with extending the depth of the collider is that the game interaction with it becomes unrealistic. In the example of our door, the extended collider protruding from the visual surface of the door would mean that we would bump into an invisible surface which would cause our character to stop in their tracks, and although we would use this collision to trigger the opening of the door through animation, the initial bump into the extended collider would seem unnatural to the player and thus detract from their immersion in the game. So while collision detection will work perfectly well between the player character collider and the door collider, there are drawbacks that call for us as creative game developers to look for a more intuitive approach, and this is where ray casting comes in. Ray casting While we can detect collisions between the player character's collider and a collider that fits the door object, a more appropriate method may be to check for when the player character is facing the door we are expecting to open and is within a certain distance of this door. This can be done by casting a ray forward from the player's forward direction and restricting its length. This means that when approaching the door, the player needn't walk right up to it—or bump into an extended collider—in order for it to be detected. It also ensures that the player cannot walk up to the door facing away from it and still open it—with ray casting they must be facing the door in order to use it, which makes sense. In common usage, ray casting is done where collision detection is simply too imprecise to respond correctly. For example, reactions that need to occur with a frame-by-frame level of detail may occur too quickly for a collision to take place. In this instance, we need to preemptively detect whether a collision is likely to occur rather than the collision itself. Let's look at a practical example of this problem. The frame miss In the example of a gun in a 3D shooter game, ray casting is used to predict the impact of a gunshot when a gun is fired. Because of the speed of an actual bullet, simulating the flight path of a bullet heading toward a target is very difficult to visually represent in a way that would satisfy and make sense to the player. This is down to the frame-based nature of the way in which games are rendered. If you consider that when a real gun is fired, it takes a tiny amount of time to reach its target—and as far as an observer is concerned it could be said to happen instantly—we can assume that even when rendering over 25 frames of our game per second, the bullet would need to have reached its target within only a few frames. In the example above, a bullet is fired from a gun. In order to make the bullet realistic, it will have to move at a speed of 500 feet per second. If the frame rate is 25 frames per second, then the bullet moves at 20 feet per frame. The problem with this is a person is about 2 feet in diameter, which means that the bullet will very likely miss the enemies shown at 5 and 25 feet away that would be hit. This is where prediction comes into play. Predictive collision detection Instead of checking for a collision with an actual bullet object, we find out whether a fired bullet will hit its target. By casting a ray forward from the gun object (thus using its forward direction) on the same frame that the player presses the fire button, we can immediately check which objects intersect the ray. We can do this because rays are drawn immediately. Think of them like a laser pointer—when you switch on the laser, we do not see the light moving forward because it travels at the speed of light—to us it simply appears. Rays work in the same way, so that whenever the player in a ray-based shooting game presses fire, they draw a ray in the direction that they are aiming. With this ray, they can retrieve information on the collider that is hit. Moreover, by identifying the collider, the game object itself can be addressed and scripted to behave accordingly. Even detailed information, such as the point of impact, can be returned and used to affect the resultant reaction, for example, causing the enemy to recoil in a particular direction. In our shooting game example, we would likely invoke scripting to kill or physically repel the enemy whose collider the ray hits, and as a result of the immediacy of rays, we can do this on the frame after the ray collides with, or intersects the enemy collider. This gives the effect of a real gunshot because the reaction is registered immediately. It is also worth noting that shooting games often use the otherwise invisible rays to render brief visible lines to help with aim and give the player visual feedback, but do not confuse these lines with ray casts because the rays are simply used as a path for line rendering. Adding the outpost Before we begin to use both collision detection and ray casting to open the door of our outpost, we'll need to introduce it to the scene. To begin, drag the outpost model from the Project panel to the Scene view and drop it anywhere—bear in mind you cannot position it when you drag-and-drop; this is done once you have dropped the model (that is, let go off the mouse). Once the outpost is in the Scene, you'll notice its name has also appeared in the Hierarchy panel and that it has automatically become selected. Now you're ready to position and scale it!  
Read more
  • 0
  • 0
  • 3522

article-image-joomla-flash-showing-maps-using-yos-ammap
Packt
18 Nov 2009
12 min read
Save for later

Joomla! with Flash: Showing maps using YOS amMap

Packt
18 Nov 2009
12 min read
Showing maps using YOS amMap Adding a map to your site may be a necessity in some cases. For example, you want to show the population of countries, or you want to show a world map to your students for teaching geography. Flash maps are always interesting as you can interact with them and can view them as you like. amMap provides tools for showing Flash maps. The amMap tool is ported as a Joomla! component by yOpensource, and the component is released with the name YOS amMap. This component has two versions—free and commercial. The commercial or pro version has some advanced features that are not available in the free version. The YOS amMap component, together with its module, allows you to display a map of the world, a region, or a country. You can choose the map to be displayed, which areas or countries are to be highlighted, and the way in which the viewers can control the map. Generally, maps displayed through the YOS amMap component can be zoomed, centered, or scrolled to left, right, top, or bottom. You can also specify a color in which a region or a country should be displayed. Installing and configuring YOS amMap To use YOS amMap with your Joomla! website, you must first download it from http://yopensource.com/en/component/remository/?func=fileinfo&id=3. After downloading and extracting the compressed package, you get the component and module packages. Install the component and module from the Extensions | Install/Uninstall screen. Once installed, you can administer the YOS amMap component from Components | YOS amMap. This shows the YOS amMap Control Panel, as shown in the following screenshot: YOS amMap Control Panel displays several icons through which you can configure and publish maps. The first thing you should do is to configure the global settings for amMap. In order to do this, click on the Parameters icon in the toolbar. Doing so brings up the dialog box, as shown in the following screenshot: In the Global Configuration section, you can enter a license key if you have purchased the commercial or the pro version of this component. For the free version, this is not needed. In this section, you can also configure the legal extensions of files that can be uploaded through this component, the maximum file size for uploads, the legal image extensions, and the allowed MIME types of all uploads. You can also specify whether the Flash uploader will be used or not. Once you have configured these fields, click on the Save button and return to YOS amMap Control Panel. Adding map files You can see the list of available maps by clicking on the Maps icon on the YOS amMap Control Panel screen or by clicking on Components | amMap | Maps. This shows the Maps Manager screen, as shown in the next screenshot. As you can see, the Maps Manager screen displays the list of available maps. By default, you find the world.swf, continents.swf, and world_with_antartica.swf map files. You will find some extra maps with the amMap bundle. You can also download the original amMap package from http://www.ammap.com/download. After downloading the ZIP package, extract it, and you will find many maps in the maps subfolder. Any map from this folder can be uploaded to the Joomla! site from the Maps Manager screen. Creating a map There are several steps for creating a map using YOS amMap. First we need to upload the package for the map. For example, if we want to display the map of the United States of America, then we need to upload the map template, the map data file, and the map settings file for the United States of America. To do this first upload the map template from the Maps Manager screen. You will find the map template for USA in the ammap/maps folder. Then we need to upload the data and the settings files. For doing so, click on the Upload link on the YOS amMap Control Panel screen. Then, in the Upload amMap screen, which is shown in the next screenshot, type the map's title (United States) in the Title field. Before clicking on the Browse button besides the Package File field, you first add the ammap_data.xml and the ammap_settings.xml files to a single ZIP file, unitedstates.zip. Now, click on the Browse button, and select this unitedstates.zip file. Then click on the Upload File & Install button. Once uploaded successfully, you see this map listed in the YOS amMap Manager screen, as shown in the next screenshot. You get this screen by clicking on the amMaps link on the toolbar. As you can see, the map that we have added is now listed in the YOS amMap Manager screen. However, the map is yet in an unpublished state, and we need to configure the map before publishing it. We need to configure its data and settings files, which are discussed in the following sections. Map data file The different regions of a map are identified by the map data file. This is an XML file and it defines the areas to be displayed on the map. The typical structure of a map data file can be understood by examining ammap_data.xml. The file has many comments that explain its structure. This file looks like as follows: <?xml version="1.0" encoding="UTF-8"?><map map_file="maps/world.swf" tl_long="-168.49" tl_lat="83.63" br_long="190.3" br_lat="-55.58" zoom_x="0%" zoom_y="0%" zoom="100%"><areas> <area title="AFGHANISTAN" mc_name="AF"></area> <area title="ALAND ISLANDS" mc_name="AX"></area> <area title="BANGLADESH" mc_name="BD"></area> <area title="BHUTAN" mc_name="BT"></area> <area title="CANADA" mc_name="CA"></area> <area title="UNITED ARAB EMIRATES" mc_name="AE"></area> <area title="UNITED KINGDOM" mc_name="GB"></area> <area title="UNITED STATES" mc_name="US"></area> <area title="borders" mc_name="borders" color="#FFFFFF" balloon="false"></area></areas><movies> <movie lat="51.3025" long="-0.0739" file="target" width="10" height="10" color="#CC0000" fixed_size="true" title="build-in movie usage example"></movie> <movie x="59.6667%" y="77.5%" file="icons/pin.swf" title="loaded movie usage example" text_box_width="250" text_box_height="140"> <description> <![CDATA[You can add description text here. This text will appear the user clicks on the movie. this description text can be html-formatted (for a list which html tags are supported, visit <u><a href="http://livedocs.adobe.com/flash/8/main/00001459.html">this page</a></u>. You can add descriptions to areas and labels too.]]> </description> </movie></movies><labels> <label x="0" y="50" width="100%" align="center" text_size="16" color="#FFFFFF"> <text><![CDATA[<b>World Map]]></text> <description><![CDATA[]]></description></label></labels><lines> <line long="-0.0739, -74" lat="51.3025, 40.43" arrow="end" width="1" alpha="40"></line> </lines></map> This code is a stripped-down version of the default ammap_data.xml file. Let us examine its structure and try to understand the meaning of each markup: <map> </map>: You define the map's structure using this markup. First, by using the map_file attribute, we declare the map file that should be used to display this map. This markup has some other attributes through which we declare the top and the left offset in longitude and latitude. We can also specify the zooming level using the zoom_x, zoom_y, and zoom attributes. <areas> </areas>: Areas are the regions or countries on a map. These are defined in the map. We only need to define the areas that we want to display. For example, in the sample, we have defined eight countries to be displayed and one straight line. Each area element has several attributes, among which you need to mention mc_name and title. You specify the area's name in mc_name, which is predefined in the map template. The title element will be displayed as the title of that map area. For example, <area mc_name="BD" title="Bangladesh"></area> means the areas marked as BD in the map template will be displayed with the title Bangladesh. In order to specify the mc_name element, you need to follow the map template designer's instructions. <movies> </movies>: Movies are some extra clips that can be displayed as a separate layer on the map. For example, to display the capital of each country, a movie clip could be displayed in the specified latitude and longitude. You can also display some other animations or text using a movie definition. <labels> </labels>: The <labels> markup contains the text to be displayed on the map. You can add any text on a map by defining a label element. To view and edit the map data file, ammap_data.xml, click on the map name on the YOS amMap Manager screen. This opens-up the amMap: [Edit] screen, as shown in the following screenshot: The amMap: [Edit] screen displays several configurations for the map. From the Details section you can change the map name, publish the map, and enable security. From the Design section you can view and edit the data and the settings files. Clicking on Data will show the data file. You can edit the data file from the online editor. As we want to display the map of USA, we will make the following changes on this screen: Select usa.swf in the Maps list. Change the data file as follows: <?xml version="1.0" encoding="UTF-8"?><map map_file="maps/usa.swf" zoom="100%" zoom_x="7.8%"zoom_y="0.18%"><areas> <area mc_name="AL" title="Alabama"/> <area mc_name="AK" title="Alaska"/> <area mc_name="AZ" title="Arizona"/> <area mc_name="AR" title="Arkansas"/> <area mc_name="CA" title="California"/> <area mc_name="CO" title="Colorado"/> <area mc_name="CT" title="Connecticut"/> <area mc_name="DE" title="Delaware"/> <area mc_name="DC" title="District of Columbia"/> <area mc_name="FL" title="Florida"/> <area mc_name="GA" title="Georgia"/> <area mc_name="HI" title="Hawaii"/> <area mc_name="ID" title="Idaho"/> <area mc_name="IL" title="Illinois"/> <area mc_name="IN" title="Indiana"/> <area mc_name="IA" title="Iowa"/> <area mc_name="KS" title="Kansas"/> <area mc_name="KY" title="Kentucky"/> <area mc_name="LA" title="Louisiana"/> <area mc_name="ME" title="Maine"/> <area mc_name="MD" title="Maryland"/> <area mc_name="MA" title="Massachusetts"/> <area mc_name="MI" title="Michigan"/> <area mc_name="MN" title="Minnesota"/> <area mc_name="MS" title="Mississippi"/> <area mc_name="MO" title="Missouri"/> <area mc_name="MT" title="Montana"/> <area mc_name="NE" title="Nebraska"/> <area mc_name="NV" title="Nevada"/> <area mc_name="NH" title="New Hampshire"/> <area mc_name="NJ" title="New Jersey"/> <area mc_name="NM" title="New Mexico"/> <area mc_name="NY" title="New York"/> <area mc_name="NC" title="North Carolina"/> <area mc_name="ND" title="North Dakota"/> <area mc_name="OH" title="Ohio"/> <area mc_name="OK" title="Oklahoma"/> <area mc_name="OR" title="Oregon"/> <area mc_name="PA" title="Pennsylvania"/> <area mc_name="RI" title="Rhode Island"/> <area mc_name="SC" title="South Carolina"/> <area mc_name="SD" title="South Dakota"/> <area mc_name="TN" title="Tennessee"/> <area mc_name="TX" title="Texas"/> <area mc_name="UT" title="Utah"/> <area mc_name="VT" title="Vermont"/> <area mc_name="VA" title="Virginia"/> <area mc_name="WA" title="Washington"/> <area mc_name="WV" title="West Virginia"/> <area mc_name="WI" title="Wisconsin"/><area mc_name="WY" title="Wyoming"/></areas><labels> <label x="0" y="60" width="100%" color="#FFFFFF" text_size="18"> <text>Map of the United States of America</text> </label></labels></map> As you can see, we have defined regions (states) on the map of USA, and towards the end of the file, we have added a label for the map. Select Yes for the Published field in the Details section. When you are done making these changes click on the Save button to save these changes. Now we will look into the map settings file. Map data files for countries are available with the amMap package. Thus, if you download amMap 2.5.1, you will get the map settings files for different countries. For example, the map data file for USA will be in the amMap_2.5.1/examples/_countries/usa folder.  
Read more
  • 0
  • 0
  • 4599

article-image-quality-assurance-asterisk-16
Packt
18 Nov 2009
10 min read
Save for later

Quality Assurance in Asterisk 1.6

Packt
18 Nov 2009
10 min read
The world has changed quite a bit in the last 150 years. Over this time, the telephone system has been invented, improved, and automated. Telephone switches no longer refer to people sitting in a large room connecting wires between the appropriate jacks. Flexible and powerful telephone service has moved from a dream to an expectation in large businesses, and for most of us it is a necessity. Today, telephone systems are the lifeblood of business. They are how we take orders, acquire supplies, and even call for emergency assistance. With the increase in prominence of telephones, the expectations of telephone users have increased proportionally. Not only have the technological expectations for telephone systems increased dramatically, but consumers are expecting more and more out of the businesses they call. Customers expect to be helped quickly and professionally. They want to know everything in a matter of minutes. Roads do not hold the only rage our society is facing today. As a business we have a variety of questions relating to our telephone system such as: How are our personnel handling angry callers? Are our employees answering the calls in a reasonable amount of time? Do we have any workers using the phone system for personal calls when they should be doing their job? We will never be able to make sure everybody does what they are supposed to do all of the time. What we will be able to do at the end of this article is perform spot-checks on how we are doing on customer service, and make sure our phone service isn't being used for unauthorized purposes. Ultimately, it comes down to a matter of trust; however, some people do not know better because they haven't been fully trained. Most will always act honorably; however, some just cannot and should not be trusted. We will try to find out who is who. Call Detail Records When we talk about security, what images come to mind? May be a big, burly guard? Perhaps a bunch of guys in green, carrying machine guns? Do we imagine a person with a metal-detecting wand? Or do we think of thick glass window panes? All of these are security features. It is just that some are a little more intrusive than others. Each time we increase security, we become a little bit less friendly. We all have to decide how far we are willing (and able) to go. In the continuum of security, Call Detail Records are the least intrusive. No special usernames or passwords have to be remembered. No fear of big brother breathing down your customers' and users' necks need be felt. We are simply doing the same thing telephone companies do—tracking what calls were made, when they were made, how long they lasted, where they came from, and a few other bits of information. This information is then available for us to review at our leisure. Asterisk gives us a few options on how we track this information. The two major choices are flat-file logging and database logging. Flat-file CDR logging By default, Asterisk includes a module called cdr_csv. Right out of the box, Asterisk logs all calls coming in and going out. The information for these calls is placed in a Comma Separated Value (CSV) file. This CSV file is located in var/log/asterisk/cdr-csv. All information is available in Master.csv, and some channels can be configured to send some information to other files as well. The benefit of using a CSV file is the simplicity. Right after compiling and installing Asterisk, this method will work. No additional configuration is required. Also, no additional network traffic is generated, and no additional services have to be installed on our server. When using the CSV form of CDR, we will see lists and lists of values. They are not very easy to parse, so here is the format, in the order in which they appear: account code: As determined by the channel (for DAHDI) or the user (for IAX and SIP) source: The source of the call destination: The destination of the call destination context caller ID channel: The channel of the source destination channel: If applicable last application: The last application run on the channel last application argument: The last argument to the last application on the channel start time: The time the call commenced answer time: The time the call was answered end time: The time the call ended duration: The difference between start time and end time billable seconds: The difference between answer time and end time, which must be less than the duration disposition: Either ANSWERED, NO ANSWER, or BUSY amaflags: As set for the channel or user, like account code uniqueid: A unique call identifier userfield: A user field set by the SetCDRUserField command We see that there are many items of information logged for each and every call. We can compare the billable seconds with our phone bill at the end of the month to make sure they're close. We can look at the destination and figure out if the calls were authorized. This gives us enough information to answer most questions we may have about a phone call. While we have enough information to answer questions, finding that answer is not very easy. We would have to scan through the entire file to try to find anything. If we are going to use an accounting package or reporting software, CSV may be exactly what we need. However, if we wish to use it in a more ad hoc sort of way, it is not very readable. Database CDR logging If we wish to read our CDR logs, it is most easily accomplished when the records are sortable. The easiest way to do this is to store our CDR records in a database. Even in this, Asterisk gives us choices. Included with Asterisk is support for PostgreSQL databases. In order to be able to install this, we must first have the postgresql-devel package installed on our system. If you have to install this package, you'll need to reinstall Asterisk. The automake system will automatically detect that we have the capability to use PostgreSQL and compile that module for us. Aside from the development packages we have installed, we will also need a PostgreSQL server somewhere in our network. It can be the same machine as the Asterisk server, but it doesn't necessarily need to be. In fact, it probably makes sense to have only one such database server on our network, and we don't want to tie up too much of our PBX's resources with database maintenance and storage. There is a script in /usr/src/asterisk/contrib/scripts/ called postgres_cdr.sql, which creates the correct table structure for us. This script should be run from the database server. If we get an error message while rebuilding that says something like "cannot find-lz", then we need to install zlib-devel. Now that we have set up our database and installed the CDR module, we must configure Asterisk to use the correct database. In order to do this, we need to edit /etc/asterisk/cdr_pgsql.conf. All of the configuration variables are in the global section. Our file should look like the following: [global]hostname=dbserver.mydomain.tldport=5432dbname=asteriskpassword=supersecretuser=asteriskuser Once we have these variables set, the next time we restart Asterisk, all CDR records will be logged in the database. If PostgreSQL is not our database of choice, we can use MySQL. This is not a part of the normal distribution of Asterisk. But as we have already installed asterisk-addons, we should already have the ability to use MySQL for CDR logging. Before we compile, we need to make sure that we have mysql-devel installed. First, we need to decide which version we're going to use. Because of some license quibbles, MySQL version 4.0 and later is not in the automatic package distribution chain. Instead, if we do need to download it, we will have to get it directly from www.mysql.com. However, the older version (3.x) will work with Asterisk and hence, you may wish to take a look at the differences between what version 3 offered and what later versions give us. Other than the development package mentioned, we will also need a MySQL server somewhere in our network. Just as with PostgreSQL, we can choose to have it on the same server as Asterisk, but for the same reasons, we probably shouldn't. Next, on the database server, we need to create the database with a user and a table for the CDR data. We do this by running the following code: # mysqladmin create database asteriskcdrdb # mysqlmysql> GRANT ALL PRIVILEGES   -> ON asteriskcdrdb.*   -> TO asteriskcdruser   -> IDENTIFIED BY 'changethis2yourpassword';mysql> USE asteriskcdrdb;mysql> CREATE TABLE cdr (   -> uniqueid varchar(32) NOT NULL default '',   -> userfield varchar(255) NOT NULL default '',   -> accountcode varchar(20) NOT NULL default '',   -> src varchar(80) NOT NULL default '',   -> dst varchar(80) NOT NULL default '',   -> dcontext varchar(80) NOT NULL default '',   -> clid varchar(80) NOT NULL default '',   -> channel varchar(80) NOT NULL default '',   -> dstchannel varchar(80) NOT NULL default '',   -> lastapp varchar(80) NOT NULL default '',   -> lastdata varchar(80) NOT NULL default '',   -> calldate datetime NOT NULL default '0000-00-00 00:00:00',   -> duration int(11) NOT NULL default '0',   -> billsec int(11) NOT NULL default '0',   -> disposition varchar(45) NOT NULL default '',   -> amaflags int(11) NOT NULL default '0'-> ); That's all there is to it! We only have to do this once, so it's really not so bad. Next, we have to modify the /etc/asterisk/cdr_mysql.conf file to correctly reflect our choices. [global]hostname=ourdbserver.ourdomain.tlddbname=asteriskcdrdbpassword=changethis2yourpassworduser=asteriskcdruserport=3306userfield=1 The next time we restart Asterisk, our CDR information will be stored in the MySQL database. What does that give us? We now have the ability to use a number of very powerful tools to search our CDR records to find trends and patterns.
Read more
  • 0
  • 0
  • 1680

article-image-make-spacecraft-fly-and-shoot-special-effects-using-blender-3d-249
Packt
18 Nov 2009
4 min read
Save for later

Make Spacecraft Fly and Shoot with Special Effects using Blender 3D 2.49

Packt
18 Nov 2009
4 min read
Blender particles In the last versions of Blender 3D, the particle system received a huge upgrade, making it more complex and powerful than before. This upgrade, however, made it necessary to create more parameters and options in order for the system to acts. What didn't change was the need for an object that works as emitter of the particles. The shape and look of this object will be directly related to the type of effects we want to create. Before we discuss the effects that we will be creating, let's look at how the particles work in Blender. To create any type of particle system, go to the Objects panel and find the Particles button. This is where we will set up and change our particles for a variety of effects. The first time we open this menu, nothing will be displayed. But, if we select a mesh object and press the Add New button, this object will immediately turn into a new emitter. When a new emitter is created, we have to choose the type of behavior this emitter has in the particle system. In the top-left part of the menu, we will find a selector that lets us choose the type of interaction of the emitter. These are the three types of emitters: Emitter: This is the standard type, which is a single object that emits particles according to the parameters and rules that we set up in the particles controls. Hair: Here, we have a type of particle emitter that creates particles as thin lines for representing hair and fur. Since this is more related to characters, we won't use this type of emitter in this book. Reactor: With this emitter, we can create particle systems that interact with each other. It works by setting up a particle system that interferes with the motion and changes the trajectories of other particles. In our projects, we will use only the emitter type. However, you can create indirect animations and use particles to interact with each other. For instance, if you want to create a set of asteroids that block the path of our spacecraft, we could create this type of animation easily with a reactor particle system. How particles work To create and use a particle system, we will look at the most important features and parameters of each menu and create some pre-systems to use later in this article for the spacecraft. To fully understand how particles work, we have to become familiar with the forces or parameters that control the look and feel of particles. For each of those parameters and forces, we have a corresponding menu in Blender. Here corresponding parameters that control the particle system: Quantity: This is a basic feature of any particle system that allows us to set up how many particles will be in the system. Life: As a particle system is based on animation parameters, we have to know from how many frames the particle will be visible in the 3D world. Mesh emitting: Our emitters are all meshes, and we have to determine from which part of those 3D objects the particles will be emitted. We have several options to choose from, such as vertices or parts of the objects delimited by vertex groups. Motion: If we set up our particle system and don't give it enough force to make the particles move, nothing will happen to the system. So, even more important than setting up the appearance of the particles is choosing the right forces for the initial velocity of the particles. Physics and forces: Along with the forces that we use in the motion option, we will also apply some force fields and deflectors to particles to simulate and change the trajectories of the objects based on physical reactions. Visualization: A standard particle system has only small dots as particles, but we can change the way particles look in a variety of ways. To create flares and special effects such as the ones we need, we can use mesh objects that have Halo effects and many more. Interaction: At the end of the particle life, we can use several types of actions and behaviors to control the destiny of a particle. Should it spawn a new particle or simply die when it hits a special object? These are the things we have to consider before we begin setting up the animation.
Read more
  • 0
  • 0
  • 6976

article-image-most-wanted-apache-myfaces-trinidad-12-tags-and-tag-attributes
Packt
18 Nov 2009
6 min read
Save for later

Most Wanted Apache MyFaces Trinidad 1.2 Tags and Tag Attributes

Packt
18 Nov 2009
6 min read
Component library structure Trinidad's approach to web technology is comprehensive: Aimed at full control of all the bits and pieces that make up a web application, little should be left that needs to be added. So based on such a closed world, Trinidad presents itself with a wealth of components and tags that even include very basic XHTML tags as replacements for the real XHTML originals. This is no radical replacement approach, rather it enables Trinidad to remain in full control of mechanisms such as partial-page rendering (PPR, also generally known as Ajax) that otherwise would need to deal with potentially incompatible libraries externally. The following image provides an outline of Trinidad's structural package design: Trinidad is divided into the following two namespaces: tr: It is the usual tag library id that references Trinidad's core library tags. It's a large library of over 100 components ranging from layout components and navigational components, to special viewer components that all implicitly support skinning, partial-page rendering, popup dialogs, error or info messaging, and so on. trh: It is the usual tag library id that references Trinidad's XHTML support library tags, a small companion that offers alternatives for those XHTML tags that are usually applied to build XHTML structures, for example, XHTML tables. Let us take a closer look at both namespaces. The upcoming image shows the core API's hierarchical structure. The tags are backed by two types of Trinidad classes—UIX* classes that deal with the JSF component requirements to implement specific JSF lifecycle processing methods, and Core* classes that deal with the specific properties (getters or setters). Trinidad’s XHTML tag library namespace (trh) Two groups can be distinguished from the trh namespace. The first one deals with the definition of an XHTML page and provides the developer with the following tags: <trh:html>: It is used to define the whole XHTML page, analogous to <html> <trh:head>: It is used to define the header, analogous to <head> <trh:body>: It is used to define the main contents, analogous to <body> <trh:script>: It is used to define a JavaScript to be executed, analogous to <script> <trh:tableLayout>: It is used to define an XHTML table. <trh:rowLayout>: It is used to define an XHTML table line, analogous to <tr>; note that it can also be used to display an arbitrary line, particularly when elements need to be kept in one and the same line. Alternatively, it is particularly interesting to look at the tr namespace as it provides some less heavy structures free from table constructions, for instance panelGroupLayout with a layout set to vertical or a panelBorderLayout, both generating div structures instead. <trh:cellFormat>: It is used to define an XHTML table cell as part of an XHTML table. The attributes of each tag are defined in a most consistent, and thus recognizable way. By the way, there are also tags for the construction of framesets such as trh:frame in case anyone still wants to make use of framesets. However, before we deal with the attributes let us conclude this structural overview by a look at the organization of the functionality of the core tag library. Trinidad’s core tag library namespace (tr) The following groups can be functionally distinguished which is also reflected in the packages structure of Trinidad's API (all beginning with org.apache.myfaces.trinidad.component; which has been left out here to avoid repetition). Note that, for completeness, we will also include information on the pure Java side as well as information on the few components that stem from the trh namespace: Basic document composition tags from the core API: document, stylesheet, form, subform. poll also appears here although it is not a composition tag. Form input and display tags, components from the core.input API: inputText, inputDate, inputListOfValues, and so on. Command or navigation tags from core.nav that includes two tag types: One that is focused on command tags that assumes a given form, presupposing the use of form and display tags from the foregoing group—commandButton, commandLink, goButton, goLink, and so on. The other deals exclusively with navigation: navigationTree, navigationPane, breadCrumbs, and so on. Large input and output component tags from core.data, for example, table, tree, and treeTable components. Layout component tags from core.layout, for example, all the swing-like panel tags, such as panelBorderLayout, panelHorizontalLayout, panelAccordion, showDetail, showDetailItem, and so on. Basic output components from core.output that are almost always used in a web application, for example, messages, outputText, outputLabel, spacer, statusIndicator, and so on. Model objects from core.model devised for various tags ; they provide the corresponding view models for their tag viewer counterparts, for example, SortableModel, CollectionModel and RowKeySet for tr:table, ChildPropertyTreeModel for tr:tree and ChartModel for tr:chart. A couple of converter components from trinidad.convert equip JSF and Trinidad input components with powerful JSF conversion, that is, convertNumber and convertDateTime. Validator components from trinidad.validator equip JSF and Trinidad input components with powerful JSF validation such as range validation (validateDateTimeRange) and validation by regular expression match (validateRegExp). Events and event listeners from trinidad.event add new event types and listeners specific for Trinidad components such as those that support Trinidad's dialog framework, for example, commandButton to launch a popup dialogue using LaunchEvent, ReturnEvent, and ReturnListener. It provides only a few tags, but these can be very utile, for example, fileDownloadActionListener, resetActionListener, returnActionListener, and setActionListener. There is a lot more to be found on the pure Java API side that either surfaces indirectly on the tag library as attributes, or is used implicitly by the tags themselves. Furthermore, there are utility classes and context support classes—RequestContext being probably the most prominent one because it offers a lot of functionality, for example, PPR from the server side. The following figure illustrates the Java side of things (it shows what the structure of some of the classes behind core.input look like): The preceding figure is an outline of the core.input API hierarchy. Again, we can see the typical UIX* and Core* structure. Finally, let us take a closer look at the tag attributes.
Read more
  • 0
  • 0
  • 1913
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-setting-your-moodle-grade-book
Packt
17 Nov 2009
3 min read
Save for later

Setting up your Moodle Grade Book

Packt
17 Nov 2009
3 min read
Set your classes up with no effort on your part Why would you need to "set your classes up"? Surely if the course is enroll able, your students can just enter and take part in all the activities? They can indeed, but unless you put a password (enrolment key) on the course then any students on your Moodle could enroll and take a look around. That might be fine if you have an "open door" policy to your course – but in the real world, I wouldn't expect extra students to come in and join my Advanced Level French class, and so the same might apply in Moodle.  Likewise, although my colleague and I share teaching resources and experiences, we don't actually mark each other's students' work – we have separate grade books. The same should apply to Moodle. If more than one class is sharing a Moodle course, it’s important that the classes are on different pages of the grade book rather than everyone all listed together. So how do we do this without having manually to add every single student?  If your Moodle admin hasn't done this for you already, then log in to your course and click on Groups in the course administration block: Now click on the button Create group as in the next screenshot: Write the name of your class in the Group Name box, as it might say in their timetable for example. If you wish to put a description of this class you may do so, but it isn’t necessary. Scroll down to the Enrolment key box and enter a password for this class only. (Hint: it might be easier for them to recall if you make it the name of their class) If you click Unmask you will be able to see what you are typing: Click the Save changes button, and you will be returned to the Groups page where you will see your class with (0) next to its name. That's telling you there are no students in there yet! Repeat the process with all the other classes sharing your Moodle course. Your Groups page might end up like this: And finally… click to go back to your main course page and then, in the course administration block, click on Settings. In the page that comes up next, set Group mode to Visible or Separate and in  Availability  set another password (enrollment key). This enrollment key never gets used! It is simply there to keep unwanted students out! It doesn’t matter what you set it to or even whether you yourself remember it or not.
Read more
  • 0
  • 0
  • 1701

article-image-papervision3d-external-models-part-2
Packt
17 Nov 2009
7 min read
Save for later

Papervision3D External Models: Part 2

Packt
17 Nov 2009
7 min read
Creating and loading models using SketchUp SketchUp is a free 3D modeling program, which was acquired by Google in 2006. It has been designed as a 3D modeling program that's easier to use than other 3D modeling programs. A key to its success is its easy learning curve compared to other 3D tools. Mac OS X, Windows XP, and Windows Vista operating systems are supported by this program that can be downloaded from http://sketchup.google.com/. Although there is a commercial SketchUp Pro version available, the free version works fine in conjunction with Papervision3D. An interesting feature for non-3D modelers is the integration with Google's 3D Warehouse. This makes it possible to search for models that have been contributed by other SketchUp users. These models are free of any rights and can be used in commercial (Papervision3D) projects. Exporting a model from Google's 3D Warehouse for Papervision3D There are several ways to load a model, coming from Google 3D Warehouse, into Papervision3D. One of them is by downloading a SketchUp file and exporting it to a format Papervision3D works with. This approach will be explained. The strength of Google 3D Warehouse is also its weakness. Anybody with a Google account can add models to the warehouse. This results in a variety of quality of the models. Some are very optimized and work fluently, whereas others reveal problems when you try to make them work in Papervision3D. Or they may not work at all, as they're made of too many polygons to run in Papervision3D. Take this into account while searching for a model in the 3D warehouse. For our example we're going to export a picnic table that was found on Google 3D Warehouse. Start Sketch Up. Choose a template when prompted. This example uses Simple Template – Meters, although there shouldn't be a problem with using one of the other templates. Go to File | 3D Warehouse | Get models to open 3D Warehouse inside SketchUp. Enter a keyword to search for. In this example that will be picnic table. Select a model of your choice. Keep in mind that it has to be low poly, which is something you usually find out by trial and error. Click on Download Model, to import the model into SketchUp and click OK when asked if you want to load the model directly into your Google SketchUp model. Place the model at the origin of the scene. To follow these steps, it doesn't have to be the exact origin, approximately is good enough. By default, a 2D character called Sang appears in the scene, which you do not necessarily have to remove; it will be ignored during export. Because the search returned a lot of picnic tables varying in quality, there is a SketchUp file (can be downloaded from http://www.packtpub.com/files/code/5722_Code.zip). This file has a picnic table already placed on the origin. Of course, you could also choose another picnic table, or any other object of your choice. Leave the model as it is and export it. Go to File | Export | 3D Model. Export it using the Google Earth (*.kmz) format and save it in your assets folder. T he file format we're exporting to originally was meant to display 3D objects in Google Earth. The file ends with .kmz as its extension, and is actually a ZIP archive that contains a COLLADA file and the textures. In the early days of Papervision3D, it was a common trick to create a model using SketchUp and then get the COLLADA file out of the exported Google Earth file, as the Google Earth KMZ file format wasn't still supported then. Importing a Google Earth model into Papervision3D Now that we have successfully exported a model from SketchUp, we will import it into Papervision3D. This doesn't really differ from loading a COLLADA or 3D Studio file. The class we use for parsing the created PicnicTable.kmz file is called KMZ and can be found in the parsers package. Add the following line to the import section of your document class: import org.papervision3d.objects.parsers.KMZ; Replace or comment the code that loads the animated COLLADA model and defines the animations from the previous example. In the init() method we can then instantiate the KMZ class, assign it to the model class property, and load the KMZ file. Make sure you have saved PicnicTable.kmz file into the assets folder of your project. model = new KMZ();model.addEventListener(FileLoadEvent.LOAD_COMPLETE,modelLoaded);KMZ(model).load("assets/PicnicTable.kmz"); ExternalModelsExample That looks familiar, right? Now let's publish the project and your model should appear on the screen. Notice that in many cases, the downloaded and exported model from Google 3D Warehouse might appear very small on your screen in Papervision3D. This is because they are modeled with other metric units than we use in Papervision3D. Our example application places the camera at a 1000 units away from the origin of the scene. Many 3D Warehouse models are made using units that define meters or feet, which makes sense if you were to translate them to real-world units. When a model is, for example, 1 meter wide in SketchUp, this equals to 1 unit in Papervision3D. As you can imagine, a 1 unit wide object in Papervision3D will barely be visible when placing the camera at a distance of 1000. To solve this you could use one of the following options: Use other units in Papervision3D and place your camera at a distance of 5 instead of 1000. Usually you can do this at the beginning of your project, but not while the project is already in progress, as this might involve a lot of changes in your code due to other objects, animations, and calculations that are made with a different scale. Scale your model inside SketchUp to a value that matches the units as you use them in Papervision3D. When the first option can't be realized, this option is recommended. Scale the loaded model in Papervision3D by changing the scale property of your model. model.scale = 20; Although this is an option that works, it's not recommended. Papervision3D has some issues with scaled 3D objects at the time of writing. It is a good convention to use the same units in Papervision3D and your 3D modeling tool. If you want to learn more about modeling with SketchUp, visit the support page on the SketchUp web site http://sketchup.google.com/support. You'll find help resources such as video tutorials and a help forum. Creating and loading models using Blender Blender is an open source, platform-independent 3D modeling tool, which was first released in 1998 as a shareware program. It went open source in 2002. Its features are similar to those in commercial tools such as 3ds Max, Maya, and Cinema4D. However, it has a reputation of having a difficult learning curve compared to other 3D modeling programs. Blender is strongly based on usage of keyboard shortcuts and not menus, which makes it hard for new users to find the options they're looking for. In the last few years, more menu-driven interfaces have been added. It's not in the scope of this article to teach you everything about the modeling tools that can be used with Papervision3D. This also counts for Blender. There are many resources such as online tutorials and books that cover how to work with Blender. A link to the Blender installer download can be found on its web site: www.blender.org.
Read more
  • 0
  • 0
  • 2020

article-image-providing-context-using-custom-text-upk-35
Packt
17 Nov 2009
10 min read
Save for later

Providing context using Custom Text in UPK 3.5

Packt
17 Nov 2009
10 min read
The Start Frame You may recall that the very first Frame in a Topic is the Start Frame. This is sometimes referred to as the Introduction frame, which is largely a throwback to OnDemand, as we shall see shortly. As this Frame is the first thing that a trainee will see when they carry out a Topic, coupled with the fact that this Frame is a "non-action" Frame, in that the user does not need to actively do anything (other than pressing Enter to continue), it is a good place to provide some additional information to the trainee. The first thing that you should explain in the Introduction frame is exactly what the trainee will be learning in the exercise. Certainly the title of the Topic should give them a clue, but this is not really detailed enough. A good source of information for this is the learning objectives of the course for which this exercise has been built, or the competencies, depending on your curriculum development process. For our sample exercise, we could use the bubble shown in the following screenshot: This is a good start, but we can do more. It is always useful, with training exercises, to use realistic business scenarios to explain what the trainee is doing, to put the keystrokes and mouse-clicks into a business context. Trainees are much more likely to remember information to which they can relate. Consider telling a story and walking the trainees through that story as they carry out the exercise. Although it is a fairly spurious example, we will continue with our sample exercise. Here, we could use the bubble shown in the following screenshot: So now the trainee has a good idea of what they will learn, and they have an example that they can relate to. The text is also directed at the trainee, so the trainee will feel actively involved. There is another strong argument for including a scenario in the form shown above. Consider the case where you are providing training for users in multiple locations (possibly countries) or departments, each of which has its own set of customers, products, and vendors. Users will always want to see exercises using their data: orders for their products, placed at their location, and so on. To keep everyone happy, you would need to develop a separate, customized Topic for each location or user group. If the basic process (and, most importantly for us, the Actions in the recording) is the same in each case, this is clearly inefficient. However, if you create a scenario, and say something like "You are a Customer Service Representative in the Tampa Service Center. Customer SunCo has phoned through an order for 1,000 gallons of regular gasoline. You need to record this order in the system so that it can be fulfilled by Fuel Services." then trainees who are not at the Tampa Service Center will at least understand that this is role play. It is make believe, and they shouldn't be concerned that they don't see products that they don't supply at their own location. So set the scene with a scenario in the Introduction pane, and then build on this throughout the exercise. Introduction Text: Version differences At this point, it is worth highlighting some key differences between the way the Introduction pane was handled prior to UPK 3.5, and the way that the Introduction pane is used in UPK 3.5. If you open an Outline Element in the Outline Editor, and select a Topic in the navigation tree, you will see that the lower-right portion of the screen is labeled Introduction, as shown in the following screenshot: The Outline Editor is used to organize content objects into the structure that the trainee will see. However, if we look at the published version of the Outline above, we will see the following: Where has the Introduction Frame gone? Put simply. UPK 3.5 does not display the Introduction Frame in the Player any more. Users of UPK 2.x or OnDemand 9.x will recall that the Introduction Frame certainly used to be displayed, as shown in the following screenshot, which is taken from OnDemand 9.1.5: Quite why Oracle decided to change the way the Introduction pane is displayed (or not) in version 3.5 is a mystery (maybe they felt that with all that screen space required for the new Oracle branding, there just wasn't the space left to include the Introduction any more). However, it does have some important implications on the way that we are planning on using it. This is because the effect of a publishing option associated with the Introduction pane has changed significantly. In the Publishing Wizard, the options for the Player package include an option to Show introduction text. In OnDemand version 9.1, this option determined whether the Introduction text appeared in the Outline as well as on the first Frame of the Player. However, in UPK 3.5, the Introduction text is never displayed in the Outline and the Show introduction text determines whether the Introduction text appears in the Player at all (effectively, it controls whether the Start Frame is included in the Player or not. Version Difference The Content Development manual for OnDemand 9.1.5 describes the Show introduction text option as working the way described for UPK 3.5. It doesn't work that way; it works the way described for OnDemand 9.1, above. This is clearly a rare case of the documentation being updated before the software. For our purposes, therefore, we need to make sure that the Show introduction text option is always selected when we publish. This option can be found in the Player category of your Options, as shown in the next screenshot: Action Frames It is possible to add Custom Text to the Topic's Bubbles, either in addition to, or instead of, the Template Text. Using the Template Text has several significant advantages, especially when localizing your content or providing sound. However, the Template Text will only ever be able to describe the mechanics of what the user is doing, it cannot provide business context. You should always try to teach more than just key-strokes and mouse-clicks. Specifically, you should always take the opportunity to add business context yourself, through the liberal use of Custom Text in Action Frames. Consider the following example that uses solely the default template texts: Certainly the trainee can carry out the required action and work their way through the exercise, but are they really learning anything? What is the Ext.Ref field, and what is the significance of the value ZBW002342? Should they always enter this value, or are other values possible? Here, we should help the trainee out and teach them something by providing some more information through the use of Custom Text. A better version is shown in the following screenshot: Now the trainee knows exactly what they are entering in the exercise, and understands the business context so they can perform the action correctly when they are doing their actual job. Note that here, we have retained the Template Text (we did not insert the Template Text as Custom Text) which will aid in the translation (although the custom text will still need to be manually translated). We simply added the first paragraph that you see in the Bubble above as Custom Text, and positioned it before the Template Text (the Show custom text first button () is selected by default; you can deselect this if required, to have the Template Text displayed first, but for our purposes we want the Custom Text first).   UPK will run the Template Text in the next line immediately after the Custom Text, so you need to insert an extra line break at the end of the Custom Text if you want the two texts to appear as separate paragraphs. In this example, note that we have continued the scenario that we described in the Introduction pane through into this exercise, by mentioning the customer's name. Again, it is always useful to use a scenario so that the trainee can better relate the exercise to their actual jobs. Note that the text For this exercise...is ZBW002342 will need to be tagged to appear only in See It! and Try It! modes. UPK will run the Template Text in the next line immediately after the Custom Text, so you need to insert an extra line break at the end of the Custom Text if you want the two texts to appear as separate paragraphs. In this example, note that we have continued the scenario that we described in the Introduction pane through into this exercise, by mentioning the customer's name. Again, it is always useful to use a scenario so that the trainee can better relate the exercise to their actual jobs. Note that the text For this exercise...is ZBW002342 will need to be tagged to appear only in See It! and Try It! modes. Whenever practical, you should try to provide some more information, whether this is business context, or a continuation of the scenario you are using, even if this is on every Frame. If you intend for your simulations being used outside of a classroom environment, then you should consider providing exactly the same level of information as the instructor would provide in a classroom. Think about what you would say to the trainee, what additional information or guidance you would give them if you sat next to them, talking them through the simulation, and then add that information into the Bubbles as Custom Text. Remember: training is the effective transfer of knowledge, and if that knowledge is incomplete, then the trainees have not been adequately trained. The End Frame The End Frame is always displayed as the final Frame in the simulation. There is no End Frame equivalent of the Show introduction text option to avoid having this Frame displayed. This is a good thing, as it means that we can use this Frame to provide some final information to the user. This should be seen as a companion to the Start Frame, and should confirm the information presented in the Start Frame. In the Start Frame above, we told the trainee what they would learn. In the End Frame, we should confirm that they have learned this. (This much is standard training theory.) If you have described a scenario in the Start Frame, and followed this through the Action Frames, then you should make reference to this, as well. Suitable End Frame text for our ongoing exercise on SAP user options could be: Although the scenario information is again fairly spurious in this example, it does at least give you an idea of the kind of information that can usefully be included in the End Frame. Again, this information should be tagged for See It! and Try It! modes only. Note that in this example we have also included a message of You have now completed this exercise. This is a nice courtesy, and confirms to the trainee that they have reached the end of the simulation.
Read more
  • 0
  • 0
  • 3854

article-image-create-quick-application-cakephp-part-1
Packt
17 Nov 2009
9 min read
Save for later

Create a Quick Application in CakePHP: Part 1

Packt
17 Nov 2009
9 min read
The ingredients are fresh, sliced up, and in place. The oven is switched on, heated, and burning red. It is time for us to put on the cooking hat, and start making some delicious cake recipes. So, are you ready, baker? In this article, we are going to develop a small application that we'll call the "CakeTooDoo". It will be a simple to-do-list application, which will keep record of the things that we need to do. A shopping list, chapters to study for an exam, list of people you hate, and list of girls you had a crush on are all examples of lists. CakeTooDoo will allow us to keep an updated list. We will be able to view all the tasks, add new tasks, and tick the tasks that are done and much more. Here's another example of a to-do list, things that we are going to cover in this article: Make sure Cake is properly installed for CakeTooDoo Understand the features of CakeTooDoo Create and configure the CakeTooDoo database Write our first Cake model Write our first Cake controller Build a list that shows all the tasks in CakeTooDoo Create a form to add new tasks to CakeTooDoo Create another form to edit tasks in the to-do list Have a data validation rule to make sure users do not enter empty task title Add functionality to delete a task from the list Make separate lists for completed and pending Tasks Make the creation and modification time of a task look nicer Create a homepage for CakeTooDoo Making Sure the Oven is Ready Before we start with CakeTooDoo, let's make sure that our oven is ready. But just to make sure that we do not run into any problem later, here is a check list of things that should already be in place: Apache is properly installed and running in the local machine. MySQL database server is installed and running in the local machine. PHP, version 4.3.2 or higher, is installed and working with Apache. The latest 1.2 version of CakePHP is being used. Apache mod_rewrite module is switched on. AllowOverride is set to all for the web root directory in the Apache configuration file httpd.conf. CakePHP is extracted and placed in the web root directory of Apache. Apache has write access for the tmp directory of CakePHP. In this case, we are going to rename the Cake directory to it CakeTooDoo. CakeTooDoo: a Simple To-do List Application As we already know, CakeTooDoo will be a simple to-do list. The list will consist of many tasks that we want to do. Each task will consist of a title and a status. The title will indicate the thing that we need to do, and the status will keep record of whether the task has been completed or not. Along with the title and the status, each task will also record the time when the task has been created and last modified. Using CakeTooDoo, we will be able to add new tasks, change the status of a task, delete a task, and view all the tasks. Specifically, CakeTooDoo will allow us to do the following things: View all tasks in the list Add a new task to the list Edit a task to change its status View all completed tasks View all pen Delete a task A homepage that will allow access to all the features. You may think that there is a huge gap between knowing what to make and actually making it. But wait! With Cake, that's not true at all! We are just 10 minutes away from the fully functional and working CakeTooDoo. Don't believe me? Just keep reading and you will find it out yourself. Configuring Cake to Work with a Database The first thing we need to do is to create the database that our application will use. Creating database for Cake applications are no different than any other database that you may have created before. But, we just need to follow a few simple naming rules or conventions while creating tables for our database. Once the database is in place, the next step is to tell Cake to use the database. Time for Action: Creating and Configuring the Database Create a database named caketoodoo in the local machine's MySQL server. In your favourite MySQL client, execute the following code: CREATE DATABASE caketoodoo; In our newly created database, create a table named tasks, by running the following code in your MySQL client: USE caketoodoo; CREATE TABLE tasks ( id int(10) unsigned NOT NULL auto_increment, title varchar(255) NOT NULL, done tinyint(1) default NULL, created datetime default NULL, modified datetime default NULL, PRIMARY KEY (id) ); Rename the main cake directory to CakeTooDoo, if you haven't done that yet. Move inside the directory CakeTooDoo/app/config. In the config directory, there is a file named database.php.default. Rename this file to database.php. Open the database.php file with your favourite editor, and move to line number 73, where we will find an array named $default. This array contains database connection options. Assign login to the database user you will be using and password to the password of that user. Assign database to caketoodoo. If we are using the database user ahsan with password sims, the configuration will look like this: var $default = array( 'driver' => 'mysql', 'persistent' => false, 'host' => 'localhost', 'port' => '', 'login' => 'ahsan', 'password' => 'sims', 'database' => 'caketoodoo', 'schema' => '', 'prefix' => '', 'encoding' => '' ); Now, let us check if Cake is being able to connect to the database. Fire up a browser, and point to http://localhost/CakeTooDoo/. We should get the default Cake page that will have the following two lines: Your database configuration file is present and Cake is able to connect to the database, as shown in the following screen shot. If you get the lines, we have successfully configured Cake to use the caketoodoo database. What Just Happened? We just created our first database, following Cake convention, and configured Cake to use that database. Our database, which we named caketoodoo, has only one table named task. It is a convention in Cake to have plural words for table names. Tasks, users, posts, and comments are all valid names for database tables in Cake. Our table tasks has a primary key named id. All tables in Cake applications' database must have id as the primary key for the table. Conventions in CakePHPDatabase tables used with CakePHP should have plural names. All database tables should have a field named id as the primary key of the table. We then configured Cake to use the caketoodoo database. This was achieved by having a file named database.php in the configuration directory of the application. In database.php, we set the default database to caketoodoo. We also set the database username and password that Cake will use to connect to the database server. Lastly, we made sure that Cake was able to connect to our database, by checking the default Cake page. Conventions in Cake are what make the magic happen. By favoring convention over configuration, Cake makes productivity increase to a scary level without any loss to flexibility. We do not need to spend hours setting configuration values to just make the application run. Setting the database name is the only configuration that we will need, everything else will be figured out "automagically" by Cake. Throughout this article, we will get to know more conventions that Cake follows.   Writing our First Model Now that Cake is configured to work with the caketoodoo database, it's time to write our first model. In Cake, each database table should have a corresponding model. The model will be responsible for accessing and modifying data in the table. As we know, our database has only one table named tasks. So, we will need to define only one model. Here is how we will be doing it: Time for Action: Creating the Task Model Move into the directory CakeTooDoo/app/models. Here, create a file named task.php. In the file task.php, write the following code: <?php class Task extends AppModel { var $name = 'Task'; } ?> Make sure there are no white spaces or tabs before the <?php tag and after the ?> tag. Then save the file. What Just Happened? We just created our first Cake model for the database table tasks. All the models in a CakePHP application are placed in the directory named models in the app directory. Conventions in CakePHP: All model files are kept in the directory named models under the app directory. Normally, each database table will have a corresponding file (model) in this directory. The file name for a model has to be singular of the corresponding database table name followed by the .php extension. The model file for the tasks database table is therefore named task.php. Conventions in CakePHP: The model filename should be singular of the corresponding database table name. Models basically contain a PHP class. The name of the class is also singular of the database table name, but this time it is CamelCased. The name of our model is therefore Task. Conventions in CakePHP: A model class name is also singular of the name of the database table that it represents. You will notice that this class inherits another class named AppModel. All models in CakePHP must inherit this class. The AppModel class inherits another class called Model. Model is a core CakePHP class that has all the basic functions to add, modify, delete, and access data from the database. By inheriting this class, all the models will also be able to call these functions, thus we do not need to define them separately each time we have a new model. All we need to do is to inherit the AppModel class for all our models. We then defined a variable named $name in the Task'model, and assigned the name of the model to it. This is not mandatory, as Cake can figure out the name of the model automatically. But, it is a good practice to name it manually.
Read more
  • 0
  • 0
  • 3547
article-image-glossary-upk-35
Packt
16 Nov 2009
9 min read
Save for later

Glossary in UPK 3.5

Packt
16 Nov 2009
9 min read
A Glossary in UPK effectively associates Web Pages to key terms. UPK will then turn any instance of that key term within a Topic (or other content object) to which that Glossary is assigned into a hyperlink to the associated Web Page. You could do this manually by creating Web Pages (as explained above) and then creating hyperlinks to these manually, but the advantage of using the Glossary functionality is that UPK will 'automatically' find each occurrence of the glossary term and create the hyperlink. I say 'automatically' in quotation marks, as UPK does not do this completely automatically. You have to tell it to go and create the hyperlinks, but once you tell it to do so, it will dutifully go off and find 'every' occurrence of all of the terms in the glossary and create the hyperlinks to the definition. And I say 'every' in quotation marks, because UPK won't necessarily link every instance of the term. UPK allows you to choose (at the Library level) whether it turns literally every occurrence of the term found in a location into a hyperlink, or only the first occurrence. A location here is effectively a single Bubble or Web Page. One could well ask why UPK doesn't provide the option to create a Glossary link only for the first occurrence of the term in a Topic. The simple answer is that it does not necessarily know which occurrence is the first, because the Topic could include Alternative Paths. So UPK takes an over-cautious approach, and considers each block of information separately. This option is specified in the Options panel (menu option Tools|Options), under the Content Defaults|Glossary section, as shown in the following screenshot: Creating a glossary To create a Glossary in UPK, follow these steps: From the main Library screen, click on the folder within which you want to create the Glossary. You can create the Glossary in any folder, but it makes sense to have a single folder that contains the Glossary file itself, and all of the Web Pages used for the terms. Select menu option File|New|Glossary. The Glossary Editor is opened in a new tab within the UPK Developer window, as shown in the following screenshot: To create glossary entries from within the Glossary, follow these steps: Enter the glossary term in the first free Glossary Term field. Click in the Definition Link field on the same line. An ellipsis (...) is displayed on the rightmost side of the field. Click on the ellipsis. The Edit Definition Link dialog box is displayed. Click on the Create New Web Page field. The Save As dialog box is displayed. Navigate to the directory in which you want to save the Glossary definition. Again, it makes sense to save these in the same folder as the Glossary itself. The Name field will default to the glossary term specified in the Glossary Term field. It is recommended that you keep this default, and use the definition term as the Web Page name. You could use any other name, if you wanted to (UPK does not use this name to locate the definition; it uses its own, internal identifier) but using the same name will allow you to easily locate the term Web Page if you need to. Click on the Save button. A new tab is opened for the Web Page. Enter the Glossary description into this page. The Web Page will use the default font and colors. You can override these defaults, if required. Close the Web Page by clicking on the x on the rightmost side of the open tab list. You are passed back to the Glossary Editor. Enter a suitable ToolTip text for the glossary entry in the Tooltip field. This text will be displayed when the user hovers the mouse over the hyperlinked glossary term. If only whole instances of the glossary term should be turned into hyperlinks (for example, if the term is Order then "Orders" and "Ordering" will not be hyperlinked), then select the Match Whole Word option. Otherwise, make sure that this option is not selected. If only text that matches the case of the term should be turned into hyperlinks (for example, if the term is Order then "order" will not be hyperlinked), then select the Match Case field. Otherwise, make sure that this option is not selected. Repeat Steps 1 to 14 for all additional terms that you want to add to the Glossary. To create a glossary entry that uses an existing Web Page for the glossary term, follow these steps: Enter the glossary term in the first free Glossary Term field. Click in the Definition Link field on the same line. An ellipsis (...) is displayed on the rightmost side of the field. Click on the ellipsis. The Edit Definition Link dialog box is displayed. Click on the Create Link button. The Insert Hyperlink dialog box is displayed. Navigate to, and select, the Web Page that contains the glossary description. Click on OK. The Edit Definition Link dialog box is redisplayed. You can edit the Web Page directly from this dialog box, by clicking on the Edit Web Page icon. Click on OK. You are returned to the Glossary tabbed page. Once you have defined all required Glossary entries, save and close the Glossary, by following the steps shown below: Click the Save button to save your changes to the Glossary. The Save As dialog box is displayed. Navigate to the directory in which you want to save the Glossary. Enter a suitable name for the Glossary in the Name field. Close the Glossary Editor by clicking on the x on the rightmost side of the open tab list. An example of a partially-populated Glossary is shown in the next screenshot: You can see from the Definition Link column above that all of the Glossary definition files are stored in the same, single folder, called Glossary. This is the same folder that the Glossary object itself is stored in. Personally, I find it useful to keep all of the content objects for the Glossary in the same single folder. This is not strictly necessary, but it does keep things organized. You will also note that the Tooltip is the same in every case. I tend to always use the tooltip Glossary so that the user knows that the hyperlink links to the Glossary, and not to another form of Web Page. Assigning a Glossary to content objects Creating a Glossary is only half the story. You need to manually assign the Glossary to each object that you want to use that Glossary (that is, for which you want the terms specified in the Glossary to be hyperlinked to the Glossary definitions). Version Difference In OnDemand Version 8.7 and earlier, a single Glossary was created for a Title, and was automatically applied to all content objects within that Title. In UPK 3.5, it is possible to have multiple Glossaries within a single Library, so it is necessary to specify which content objects should use which Glossary. This assignment is done via the content object's Properties, as shown in the screenshot below. The Glossary property is available for Modules, Sections, Topics, and Web Pages. This means that you could potentially assign one Glossary to a Module, another Glossary to a Section within this Module, and a third Glossary to a Topic within that Section. Not that you're very likely to want to do this. But you could. The further implication of the requirement to assign a Glossary to each content object individually is that you can define multiple Glossaries, and assign different Glossaries to different objects. I'd question the wisdom of assigning one glossary to a Module, and then an entirely different Glossary to a Topic within that Module, but I can certainly see the benefit of having multiple Glossaries available in a Library that contained (for example) simulations for multiple applications; you could create application-specific Glossaries (as you no doubt do at the moment) and then assign each Glossary to only the content objects for the relevant application. The downside (for those of us who favor modularization and reuse) is that it is only possible to assign a single Glossary to any given object. So it is not possible to, say, create a company-wide Glossary and separate application-specific Glossaries, and then assign the company-wide Glossary and the relevant application-specific glossary to a single Topic. But more resourceful readers will have already worked out how to get around this limitation. Need a clue? Glossary entries are just Web Pages, and any given Web Page can be reused in multiple places. Need more help? A Web Page can be included in more than one Glossary. So you should first define Web Pages for all of your Glossary terms. You can then create multiple Glossaries (for example, one for each application), and include whichever terms' Web Pages you need to in each of the glossaries. If a term applies to two applications, then simply include the Web Page for that term in the Glossaries for both applications. Simple! Of course there is some slight duplication of effort as you need to create the entry in the actual Glossary content object twice (once in each glossary), but you are reusing the individual definitions, so it could be worse. Unfortunately, unlike Templates, it is not possible to specify a default Glossary in your user defaults. This means that this assignment must be done separately for each content object. However, there are a couple of shortcuts that UPK provides which avoid the need to assign the Glossary to content objects one by one. First, if you select multiple content objects (Modules, Sections, Topics, or Web Pages) and display the Properties pane, then you can assign the Glossary to all of the selected objects in one fell swoop. Second, if you assign a Glossary to a Module, then any new Sections or Titles that you create within that Module – that is, from within the Outline Editor – will inherit this Glossary assignment. However, it is important to note that this will only apply to new content objects. If you assign a Glossary to an outline element and then insert pre-existing content objects into this outline element, then these pre-existing content objects will not inherit the Glossary assignment. Regenerating the Glossary links Glossary links are not created (or updated) automatically. You need to tell UPK to go and search through your content objects and turn any instances of the Glossary terms into links to the Glossary definitions. This is good in that you can at least have control over when it does this, but bad in that it is easy to forget to do so.
Read more
  • 0
  • 0
  • 1713

article-image-using-web-pages-upk-35
Packt
16 Nov 2009
12 min read
Save for later

Using Web Pages in UPK 3.5

Packt
16 Nov 2009
12 min read
Using Web Pages in the Concept pane The most common use of Web Pages is to provide context information for Topics. Look at the following image of the Outline for our example course: You will see that the upper-right section of the Outline window contains a pane labeled Concept. If you want any information to be displayed in this pane, then you need to create a Web Page and attach it to the content object in the Outline. Version Difference Although the Concept pane always appears in the Outline view, if it is empty, then it does not appear in the Player. This is, thankfully, a new feature in UPK 3.5. In previous versions, the Concept pane always appeared in the Player, often appearing as a blank frame, where developers couldn't be bothered to provide any concepts. To create a new Web Page and attach it to a content object, carry out the following steps: Open the Outline containing the content object to which you want to attach the Web Page, in the Outline Editor. Click on the content object to select it. Although in this example we are attaching a Web Page to the concept pane for a Topic, Modules, and Sections also have concept panes, so you can also attach Web Pages to these as well. Click on the Create new web page button () in the Concept pane. The Save As dialog box is displayed. Navigate to the folder in which you want to save the Web Page (we will use an Assets sub-folder for all of our Web Pages), enter a name for the Web Page (it makes sense to use a reference to the content object to which the Web Page relates), and then click on the Save button. The Web Page Editor is opened on the Developer screen, as shown in the next screenshot: Enter the information that you want to appear in the Concept pane in the editor (as has already been done in the previous example). You can set the font face and size; set text to bold, italics, and underlined; change the text color, and change change the background color (again, as has been done in the earlier example). You can also change the paragraph alignment, and format numbered and bulleted lists. Once you have entered the required text, click on the Save button () to save your changes, and then close the Web Page Editor tabbed page. You are returned to the Outline Editor. Now, the Concept pane shows the contents of the Web Page, as shown in the next screenshot: Version Difference In UPK 3.5 (and OnDemand 9.1) you can only attach a single Web Page to the Concept pane. This is a change from OnDemand 8.7, where you could attach multiple Infoblocks and they would be displayed sequentially. (But note that if you convert content from OnDemand 8.7 where there are multiple Infoblocks in a single Concept pane, then all of the attached Infoblocks will be converted to a single Web Page in UPK 3.5.) The above steps explain how to attach a Web Page to the Concept pane for an exercise from the Outline. Although this is done from the Outline, the Web Page is attached to the Topic content object and not to the outline element. If you subsequently insert the same Topic in another Outline, the same Web Page will be used in the Concept pane of the new Outline. You can also attach a Web Page to the Concept pane for an exercise from within the Topic Editor. This is a useful option if you want to create concept Web Page but have not yet built an Outline to house the Topic. To do this, follow these steps: Open the Topic in the Topic Editor. Select menu option View|Concept Properties. The Concept Properties dialog box is displayed. This is very similar to the Concept pane seen in the Overview. It contains the same buttons. Create and save the Web Page as described above. When you have finished, and the Web Page is displayed in the Concept Properties dialog box, click on the OK button. Using images in Web Pages As stated above, a Web Page can contain an image. This can be instead of, or in addition to, any text (although if you only wanted to include a single image in the Web Page you could always use a Package, as explained later in this article). Images are a nice way of adding interest to a Web Page (and therefore to your training), or of providing additional information that is better explained graphically (after all, a picture is worth a thousand words). However, if you are using images in the Concept pane, then you should consider the overall size of the image and the likely width of the Concept pane, bearing in mind that the trainee may run the Player in a smaller window than the one you design. For our sample exercise, given that we are providing simulations for the SAP system, we will include a small SAP logo in the Web Page that appears in the Concept pane for our course Module. For the sake of variety, we will do this from the Library, and not from the Outline Editor. To add an image to a Web Page, carry out the steps described below. In the Library, locate the folder containing the Web Page to which you want to add the image. Double-click on the Web Page, to open it in the Web Page Editor. As before, this is opened in a separate tab in the main UPK Developer window, as can be seen in the next screenshot: Within the Web Page, position the cursor at the place in the text where you want the image to appear. Select menu option Insert|Image. The Insert Image dialog box is displayed, as shown in the next screenshot: In the Link to bar on the leftmost side of the dialog box, select the location of the image file that you want to insert into the Web Page. You can insert an image that you have already imported into your Library (for example, in a Package), an image that is located on your computer (or any attached drive) (option Image on My Computer), or an image from the Internet (option URL). For our sample exercise, we will insert an image from our computer. In the rightmost side of the dialog box, navigate to and select the image file that you want to insert into the Web Page. Click on OK. The image is inserted, as shown in the following screenshot: Save the Web Page, and close the Web Page Editor, if you have finished editing this Web Page. (We have not; we want to adjust the image, as explained below). Of course, this doesn't look too pretty. Thankfully, we can do something about this, because UPK provides some rudimentary features for adjusting images in Web Pages. To adjust the size or position of an image in a Web Page, carry out the following steps: With the Web Page open in the Web Page Editor, right-click on the image that you want to adjust, and then select Image Properties from the context menu. The Image Properties dialog box is displayed, as shown in the next screenshot: In the Alternative Text field, enter a short text description of the image. This will be used as the ToolTip in some web browsers. Under Size, select whether you want to use the original image size or not, and specify a new height and width if you choose not. Under Appearance, select a border width and indicate where the image should be aligned on the Web Page. Your choices are: Top, Middle, Bottom, Left, and Right. The first three of these (the vertical options) control the position of the image relative to the line of text in which it is located. The last two (the horizontal options) determine whether the image is left-aligned or right-aligned within the overall Web Page. Although these are two independent things (vertical and horizontal), you can only select one, so if you want the image to be right-aligned and halfway down the page, you can't do it. Click on OK to confirm your changes. Save and close the Web Page. For our sample exercise, we resized the image, set it to be right-aligned, and added a 1pt border around it (because it looked odd with a white background against the blue of the Web Page, without a border). A better option would be to use an image with a transparent background. In this example we have used an image with a solid background just for the purposes of illustration. These settings are as shown in the previous screenshot. This gives us a final Web Page as shown in the next screenshot. Note that this screenshot is taken from the Player, so that you can see how images are handled in the Player. Note that the text flows around the image. You will see that there is a little more space to the right of the image than there is above it. This is to leave room for a scrollbar. Creating independent Web Pages In the previous section, we looked at how to use a Web Page to add information to the Concept pane of a content object. In this section, we will look at how to use Web Pages to provide information in other areas. Observant readers will have noticed that a Web Page is in fact an independent content object itself. When you created a Web Page to attach to a Concept pane, you edited this Web Page in its own tabbed editor and saved it to its own folder (our Assets folder). Hopefully, you also noticed that in addition to the Create new web page button (), the Concept pane also has a Create link button () that can be used to attach an existing Web Page to the Concept pane. It should, therefore, come as no surprise to learn that Web Pages can be created independently of the Concept pane. In fact, the Concept pane is only one of several uses of Web Pages. To create a Web Page that is independent of a Concepts pane (or anything else), carry out these steps. In the Library, navigate to the folder in which you want to store the Web Page. In our example, we are saving all of the Web Pages for a module in a sub-folder called Assets within the course folder. Select menu option File|New|Web Page. A Web Page Editor tabbed page is opened up on the Developer screen. The content and use of this is exactly as described above in the explanation of how to create a Web Page from within an Outline. Enter the required information into the Web Page, and format it as required. We have already covered most of the available options, above. Once you have made your changes, click on the Save button (). You will be prompted to select the destination folder (which will default to the folder selected in Step 1, although you can change this) and a file name. Refer to the description of the Save As dialog box above for additional help if necessary. Close the Web Page Editor. You have now created a new Web Page. Now let's look at how to use it. Using Web Pages in Topics If you recall our long-running exercise on maintaining your SAP user profile, you will remember that we ask the user to enter their last name and their first name. These terms may be confusing in some countries—especially in countries where the "family name" actually comes before the "given name"—so we want to provide some extra explanation of some common name formats in different countries, and how these translate into first name and last name. We'll provide this information in a Web Page, and then link to this Web Page at the relevant place(s) within our Topic. First, we need to create the Web Page. How to do this is explained in the section Creating independent Web Pages, above. For our exercise, our created Web Page is as follows: There are two ways in which you can link to a Web Page from a Topic. These are explained separately, below. Linking via a hyperlink With a hyperlink, the Web Page is linked from a word or phrase within the Bubble Text of a Frame. (Note that it is only possible to do this for Custom Text because you can't select the Template Text to hyperlink from.) To create a hyperlink to a Web Page from within a Frame in a Topic, carry out the steps described below: Open up the Topic in the Topic Editor. Navigate to the Frame from which you want to provide the hyperlink. In our exercise, we will link from the Explanation Frame describing the Last name field (this is Frame 5B). In the Bubble Properties pane, select the text that you want to form the hyperlink (that is, the text that the user will click on to display the Web Page). Click on the Bubble text link button () in the Bubble Properties pane. The Bubble Text Link Properties dialog box is displayed. Click on the Create link button () to create a link to an existing Web Page (you could also click on the Create new web page button () to create a new Web Page if you have not yet created it). The Insert Hyperlink dialog box is displayed, as shown in the next screenshot: Make sure that the Document in Library option is selected in the Link to: bar. In the Look in: field, navigate to the folder containing the Web Page (the Assets folder, in our example). In the file list, click on the Web Page to which you want to create a hyperlink. Click on the Open button. Back in the Bubble Text Link Properties dialog box, click on OK. This hyperlink will now appear as follows, in the Player: Note that there is no ToolTip for this hyperlink. There was no opportunity to enter one in the steps above, so UPK doesn't know what to use. Version Difference In OnDemand 8.7 the Infoblock name was used as the ToolTip, but this is not the case from OnDemand 9.x onwards.
Read more
  • 0
  • 0
  • 3648

article-image-apache-geronimo-logging
Packt
16 Nov 2009
8 min read
Save for later

Apache Geronimo Logging

Packt
16 Nov 2009
8 min read
We will start by briefly looking at each of the logging frameworks mentioned above, and will then go into how the server logs events and errors and where it logs them to. After examining them, we will look into the different ways in which we can configure application logging. Apache log4j: Log4j is an open source logging framework that is developed by the Apache Software Foundation. It provides a set of loggers, appenders, and layouts, to control which messages should be logged at runtime, where they should be logged to, and in what format they should be logged. The loggers are organized in a tree hierarchy, starting with the root logger at the top of the hierarchy. All loggers except the root logger are named entities and can be retrieved by their names. The root logger can be accessed by using the Logger.getRootLogger() API, while all other loggers can be accessed by using the Logger.getLogger() API. The names of the loggers follow the rule that the name of the parent logger followed by a '.' is a prefix to the child logger's name. For example, if com.logger.test is the name of a logger, then its direct ancestor is com.logger, and the prior ancestor is com. Each of the loggers may be assigned levels. The set of possible levels in an ascending order are—TRACE, DEBUG, INFO, WARN, ERROR, and FATAL. If a logger is not assigned a level, then it inherits its level from its closest ancestor. A log statement makes a logging request to the log4j subsystem. This request is enabled only if its logging level is higher than or equal to its logger's level. If it is lower than the log, then the message is not output through the configured appenders. Log4j allows logs to be output to multiple destinations. This is done via different appenders. Currently there are appenders for the console, files, GUI components, JMS destinations, NT, and Unix system event loggers and remote sockets. Log4j is one of the most widely-used logging frameworks for Java applications, especially ones running on application servers. It also provides more features than the other logging framework that we are about to see, that is, the Java Logging API. Java Logging API: The Java Logging API, also called JUL, from the java.util.logging package name of the framework, is another logging framework that is distributed with J2SE from version 1.4 onwards. It also provides a hierarchy of loggers such as log4j, and the inheritance of properties by child loggers from parents just like log4j. It provides handlers for handling output, and formatters for configuring the way that the output is displayed. It provides a subset of the functionality that log4j provides, but the advantage is that it is bundled with the JRE, and so does not require the application to include third-party JARS as log4j does. SLF4J: The Simple Logging Facade for Java or SLF4J is an abstraction or facade over various logging systems. It allows a developer to plug in the desired logging framework at deployment time. It also supports the bridging of legacy API calls through the slf4j API, and to the underlying logging implementation. Versions of Apache Geronimo prior to 2.0 used Apache Commons logging as the facade or wrapper. However, commons logging uses runtime binding and a dynamic discovery mechanism, which came to be the source of quite a few bugs. Hence, Apache Geronimo migrated to slf4j, which allows the developer to plug in the logging framework during deployment, thereby eliminating the need for runtime binding. Configuring Apache Geronimo logging Apache Geronimo uses slf4j and log4j for logging. The log4j configuration files can be found in the <GERONIMO_HOME>/var/log directory. There are three configuration files that you will find in this directory, namely: client-log4j.properties deployer-log4j.properties server-log4j.properties Just as they are named, these files configure log4j logging for the client container (Java EE application client), deployer system, and the server. You will also find the corresponding log files—client.log, deployer.log, and server.log. The properties files, listed above, contain the configuration of the various appenders, loggers, and layouts for the server, deployer, and client. As mentioned above, log4j provides a hierarchy of loggers with a granularity ranging from the entire server to each class on the server. Let us examine one of the configuration files: the server-log4j.properties file: This file starts with the line log4j.rootLogger=INFO, CONSOLE, FILE. This means that the log4j root logger has a level of INFO and writes log statements to two appenders, namely, the CONSOLE appender and the FILE appender. These are the appenders that write to the console and to files respectively. The console appender and file appenders are configured to write to System.out and to <GERONIMO_HOME>/var/log/geronimo.log. Below this section, there is a finer-grained configuration of loggers at class or package levels. For example, log4j.logger.openjpa.Enhance=TRACE. It configures the logger for the class log4j.logger.openjpa.Enhance to the TRACE level. Note that all of the classes that do not have a log level defined will take on the log level of their parents. This applies recursively until we reach the root logger and inherit its log level (INFO in this case). Configuring application logging We will be illustrating how applications can log messages in Geronimo by using two logging frameworks, namely, log4j and JUL. We will also illustrate how you can use the slf4j wrapper to log messages with the above two underlying implementations. We will be using a sample application, namely, the HelloWorld web application to illustrate this. Using log4j We can use log4j for logging the application log to either a separate logfile or to the geronimo.log file. We will also illustrate how the logs can be written to a separate file in the <GERONIMO_HOME>/var/log directory, by using a GBean. Logging to the geronimo.log file and the command console Logging to the geronimo.log file and the command console is the simplest way to do application logging in Geronimo. For enabling this in your application, you only need to add logging statements to your application code. The HelloWorld sample application has a servlet called HelloWorldServlet, which has the following statements for enabling logging. The servlet is shown below. package com.packtpub.hello;import java.io.*;import javax.servlet.ServletException;import javax.servlet.http.*;import org.apache.log4j.Logger;public class HelloWorldServlet extends HttpServlet{ Logger logger = Logger.getLogger(HelloWorldServlet.class.getName()); protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.print("<html>"); logger.info("Printing out <html>"); out.print("<head><title>Hello World Application</title></head>"); logger.info("Printing out <head><title>Hello World Application</title></head>"); out.print("<body>"); logger.info("Printing out <body>"); out.print("<b>Hello World</b><br>"); logger.info("Printing out <b>Hello World</b><br>"); out.print("</body>"); logger.info("Printing out </body>"); out.print("</html>"); logger.info("Printing out </html>"); logger.warn("Sample Warning message"); logger.error("Sample error message"); }} Deploy the sample HelloWorld-1.0.war file, and then access http://localhost:8080/HelloWorld/. This servlet will log the following messages in the command console, as shown in the image below: The geronimo.log file will have the following entries: 2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out <html>2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out <head><title>Hello World Application</title></head>2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out <body>2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out <b>Hello World</b><br>2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out </body>2009-02-02 20:01:38,906 INFO [HelloWorldServlet] Printing out </html>2009-02-02 20:01:38,906 WARN [HelloWorldServlet] Sample Warning message2009-02-02 20:01:38,906 ERROR [HelloWorldServlet] Sample error message Notice that only the messages with a logging level of greater than or equal to WARN are being logged to the command console, while all the INFO, ERROR, and WARN messages are logged to the geronimo.log file. This is because in server-log4j.properties the CONSOLE appender's threshold is set to the value of the system property, org.apache.geronimo.log.ConsoleLogLevel, as shown below: log4j.appender.CONSOLE.Threshold=${org.apache.geronimo.log.ConsoleLogLevel} The value of this property is, by default, WARN. All of the INFO messages are logged to the logfile because the FILE appender has a lower threshold, of TRACE, as shown below: log4j.appender.FILE.Threshold=TRACE Using this method, you can log messages of different severity to the console and logfile to which the server messages are logged. This is done for operator convenience, that is, only high severity log messages, such as warnings and errors, are logged to the console, and they need the operator's attention. The other messages are logged only to a file.
Read more
  • 0
  • 0
  • 2894
article-image-session-and-user-joomla-15-part-2
Packt
16 Nov 2009
8 min read
Save for later

The Session and the User with Joomla! 1.5: Part 2

Packt
16 Nov 2009
8 min read
Getting the user's group ID and type The following organized list describes the user groups in Joomla! 1.5 in a way in which we are all probably familiar. Each of these groups has an ID and a name; these are the group's ID and type respectively. This recipe explains how to find the group ID and group type of the current user. Note that the hard coded group IDs should not generally be used for access control; for this it is best to take advantage of the JAuthorization class. For more information, refer to the Joomla! API site: http://api.joomla.org/. Dynamic permissions There is no administrative functionality that allows the modification of groups. It is, however, possible to programmatically modify groups and group permissions. Most of the time a Joomla! 1.5 extension will opt to implement its own permission management rather than use the incomplete Joomla! solution. Joomla! 1.6, in development at the time of writing, promises a complete GACL (Group Access Control List) implementation. Getting ready To complete this recipe, we need the JUser object that represents the current user. For more information, refer to the Getting the user recipe covered earlier in this article. $user =& JFactory::getUser(); How to do it... The group ID is held in the gid field in the #__users table. We use the JUser::get() method to extract the user's group ID. // determine group ID$groupID = $user->get('gid'); The group type is held in the usertype field in the #__users table. Again, we use the JUser::get() method to extract the user's group ID. $usertype = $user->get('usertype'); How it works... Apart from the obvious format of the data, there is a subtle difference between the gid and usertype fields. The gid field is always populated, where as the usertype field is populated only if the user is not blocked. When dealing with the current user, the user will never be blocked, but when dealing with other users there is a possibility that the usertype field will not be populated. Therefore, we need to be careful that we select the most appropriate field, depending on the context of what we are doing. The user groups that we have mentioned are maintained in the #__core_acl_aro_groups table, or as it can also be called, the Access Control List Access Request Object Groups table. This table holds a tree structure, as indicated in the introduction of the recipe. What is noticeable is that Public Frontend and Public Backend are both technically user groups. As this is a tree structure, we can use the left and right values to perform all sorts of neat tricks. The #__core_acl_aro_groups table employs the nested set model: http://dev.mysql.com/tech-resources/articles/hierarchical-data.html. See also The next recipe explains how to use the Public, Registered, and Special access levels. Restricting a user's access using Public, Registered, and Special In Joomla! we often define access based on three simple access levels. These levels relate to the user groups described in the previous recipe, Getting the user's group ID and type. This recipe explains how to use these access levels to restrict access to resources. Public (0) Registered (1) Special (2) Getting ready To complete this recipe, we need the JUser object that represents the current user. For more information, refer to the Getting the user recipe covered earlier in this article. $user =& JFactory::getUser(); How to do it... The JUser::get() method can be used to retrieve the user's aid. This is the access level number, as shown in braces in the recipe introduction. // get access level$aid = $user->get('aid'); For each resource we want to restrict access to, we must define the required access level. This is normally done in a database TINYINT(3) field named access. This can then be used to restrict the access using a database query (used when listing)... // get the DBO$db =& JFactory::getDBO();// prepare access field name$access = $db->nameQuote('access');// restrict query by access level$where = "WHERE $access <= " . intval($aid); ...or when viewing a single record. Note that ALERTNOTAUTH is a core translation string, which in en-GB is equivalent to You are not authorised to view this resource. // make sure the user has the necessary access rightsif ($table->get('access') > $aid) { JError::raiseError(403, JText::_('ALERTNOTAUTH')); jexit();} How it works... A good example of this in action is the content component. If we take a look at the article manager, we can see that there is an Access Level associated with each article that determines which users can access the article. These access levels are relatively primitive and we don't have any bona fide control over them. So how do they translate into concrete user groups? The following table describes the seven user groups and the guest group, and shows how these relate to the access levels: User Group User Group ID Access Level Access Level ID None (Guest) 0 Public 0 Registered 18 Registered 1 Author 19 Special 2 Editor 20 Special 2 Publisher 21 Special 2 Manager 23 Special 2 Administrator 24 Special 2 Super Administrator 25 Special 2 See also The previous recipe explains how to work with the user group ID and group type. This can also be useful for dealing with access control. Getting the user's parameters User parameters provide a mechanism for including additional user data without the need to modify the database. The core user parameters are defined in the XML files located in the administratorcomponentscom_usersmodels folder. Getting ready To complete this recipe, we need the JUser object that represents the current user. For more information, refer to the Getting the user recipe. $user =& JFactory::getUser(); How to do it... To retrieve a parameter we must first know the name of the parameter we want to retrieve. One example of a common parameter is timezone. This is an integer that defines the hours offset from UTC (Coordinated Universal Time), also known as GMT (Greenwich Mean Time) and Z (Zulu). To retrieve a parameter, we can use the JUser::getParam() method. $timezone = $user->getParam('timezone'); It is also possible to provide a default value. This is useful especially if the user we are dealing with is a guest because guest users do not have any parameters defined by default. $timezone = $user->getParam('timezone', '0'); How it works... A user's parameters are represented as a JParameter object. We do not have to interact directly with this object because JUser will do this for us. A minor problem with this method is the default value. Technically the XML files define the default values, but by default these XML files are not loaded by the JUser class. Therefore, the XML defined default values are not employed. One way to overcome this is to interact directly with the JParameter object. The next section explains how to do this. There's more... The JUser::getParamters() method allows us to directly access the user's JParameter object. Note that we must use =& when assigning the return value to a variable. If we do not and we are using a PHP version prior to PHP 5, we will inadvertently create a copy of the returned JParameter object. // get parameters with XML definition file loaded$params =& $user->getParameters(true); When we retrieve the JParameter object there are two optional parameters. The first parameter $loadsetupfile determines whether or not the XML file that defines the user's parameters should be loaded. Loading this file gives meaning to the data and also provides default values for defined data. For information about the second optional parameter, refer to the recipe, Extending and editing user parameters. To retrieve a value, we use the JParameter::get() method. We pass two parameters to this method—the name of the parameter we want the value of, and the default value to return if the parameter does not exist. // get timezone (hours UTC offset)$timezone = $params->get('timezone', '0'); See also The next recipe, Setting the user's parameters, explains how to set a value in the user's parameters. Setting the user's parameters User parameters provide a mechanism for including additional user data without the need to modify the database. The parameters are defined in the XML files located in the administratorcomponentscom_usersmodels folder. User parameters are not restricted to the parameters defined in the XML files. It is perfectly acceptable to add additional parameters. Getting ready To complete this recipe, we need the JUser object that represents the current user. For more information, refer to the Getting the user recipe. $user =& JFactory::getUser(); How to do it... To set the value of a parameter, we use the JUser::setParam() method. This method requires two parameters—the name of the parameter we want to set and the value to which we want to set the parameter. For example, we could change the user's editor preference to use no editor. // set value of someparameter to some value$user->setParam('editor', 'none'); There's more... If we have retrieved the JParamter object directly from the user, we can alternatively use that object to set the user's parameters. For information about retrieving the user's parameters, refer to the previous recipe, Getting the user's parameters. To set data in the JParameter object, we use the JParameter::set() method. // set value of someparameter to some value$params->set('editor', 'none'); See also The previous recipe explains how to get a value from the user's parameters.
Read more
  • 0
  • 0
  • 1604

article-image-session-and-user-joomla-15-part-1
Packt
16 Nov 2009
9 min read
Save for later

The Session and the User with Joomla! 1.5: Part 1

Packt
16 Nov 2009
9 min read
Introduction When a user starts browsing a Joomla! web site, a PHP session is created. Hidden away in the session is user information, this information will either represent a known registered user or a guest. We can interact with the session using the session handler, a JSession object. When we work with the session in Joomla!, we must not use the global PHP $_SESSION variable or any of the PHP session functions. Getting the session handler To interact with the session we use the session handler; this is a JSession object that is globally available via the static JFactory interface. It is imperative that we only use the global JSession object to interact with the PHP session. Directly using $_SESSION or any of the PHP session functions could have unintended consequences. How to do it... To retrieve the JSession object we use JFactory. As JFactory returns an object, we must use =& when assigning the object to a variable. If we do not and our server is running a PHP version prior to PHP 5, we will inadvertently create a copy of the global JSession object. $session =& JFactory::getSession(); How it works... If we look at the JSession class, we will notice that there is a getInstance() method. It is tempting to think of this as synonymous with the JFactory::getSession() method. There is, however, an important difference, the JSession::getInstance() method requires configuration parameters. The JFactory::getSession() method accepts configuration parameters, but they are not required. The first time the JFactory::getSession() method is executed, it is done by the JApplication object (often referred to as mainframe). This creates the session handler. It is the application and JFactory that deal with the configuration of the session. Subsequent usage of the JFactory::getSession() method will not require the creation of the object, and thus simply returns the existing object. The following sequence diagram shows how this process works the first time it is executed by the JApplication object: When the JFactory::getSession() method is subsequently executed, because session will already exist, the _createSession() method is not executed. The diagram is a simplification of the process; additional complexity has not been included because it is outside the scope of this recipe. See also For information about setting and retrieving values in the session, refer to the next two recipes, Adding data to the session and Getting session data. Adding data to the session Data that is set in the session is maintained between client requests. For example, we could display announcements at the top of all our pages and include an option to hide the announcements. Once a user opts to hide the announcements, by setting a value in the session, we would be able to 'remember' this throughout the user's visit. To put this into context, we would set a session value hideAnnouncements to true when a user opts to hide announcements. In subsequent requests, we will be able to retrieve the value of hideAnnouncements from the session and its state will remain the same. In Joomla!, session data is maintained using a JSession object, which we can retrieve using JFactory. This recipe explains how to set data in the session using this object instead of using the global PHP $_SESSION variable. Getting ready We must get the session handler, a JSession object. For more information, refer to the first recipe in this article, Getting the session handler. $session =& JFactory::getSession(); How to do it... The JSession::set() method is used to set a value in the session. The first parameter is the name of the value we want to set; the second is the value itself. $session->set('hideAnnouncements', $value); The JSession::set() method returns the previous value. If no value was previously set, the return value will be null. // set the new value and retrieve the old$oldValue = $session->set('hideAnnouncements', $value);echo 'Hide Announcement was ' . ($oldValue ? 'true' : 'false');echo 'Hide Announcement is now ' . ($value ? 'true' : 'false'); Lastly, we can remove data from the session by setting the value to null. // remove something$session->set('hideAnnouncements', null); How it works... The session contains a namespace-style data structure. Namespaces are required by JSession and by default all values are set in the default namespace. To set a value in a different namespace, we use the optional JSession::set() third parameter. $session->set('something', $value, 'mynamespace'); Sessions aren't just restricted to storing basic values such as strings and integers. The JUser object is a case in point—every session includes an instance of JUser that represents the user the session belongs to. If we add objects to the session, we must be careful. All session data is serialized. To successfully unserialize an object, the class must already be known when the session is restored. For example, the JObject class is safe to serialize because it is loaded prior to restoring the session. $value = new JObject();$session->set('aJObject', $value); If we attempt to do this with a class that is not loaded when the session is restored, we will end up with an object of type __PHP_Incomplete_Class. To overcome this, we can serialize the object ourselves. // serialize the object in the session$session->set('anObject', serialize($anObject)); To retrieve this, we must unserialize the object after we have loaded the class. If we do not do this, we will end up with a string that looks something like this O:7:"MyClass":1:{s:1:"x";s:10:"some value";}. // load the classinclude_once(JPATH_COMPONENT . DS . 'myclass.php');// unserialize the object from the session$value = unserialize($session->get('anObject')); There's more... There is an alternative way of setting data in the session. User state data is also part of the session, but this data allows us to save session data using more complex hierarchical namespaces, for example com_myextension.foo.bar.baz. To access this session data, we use the application object instead of the session handler. // get the application$app =& JFactory::getApplication();// set some data$app->setUserState('com_myextsion.foo.bar.baz, $value); An advantage of using user state data is that we can combine this with request data. For more information refer to the next recipe, Getting session data. The JApplication::setUserState() method is documented as returning the old value. However, a bug prevents this from working; instead the new value is returned. See also For information about retrieving values from the session, refer to the next recipe, Getting session data. Getting session data Data that is set in the session is maintained between client requests. For example if during one request we set the session value of hideAnnouncements to true, as described in the previous recipe, in subsequent requests we will be able to retrieve the value of hideAnnouncements and its state will remain the same. In Joomla!, session data is maintained using the global JSession object. This recipe explains how to get data from the session using this object instead of from the normal global PHP $_SESSION variable. Getting ready We must get the session handler, a JSession object. For more information, refer to the first recipe in this article, Getting the session handler. $session =& JFactory::getSession(); How to do it... We use the JSession::get() method to retrieve data from the session. $value = $session->get('hideAnnouncements'); If the value we attempt to retrieve is not set in the session, the value null is returned. It is possible to specify a default value, which will be returned in instances where the value is not currently set in the session. $defaultValue = false;$value = $session->get('hideAnnouncements', $defaultValue); How it works... The session contains a namespace-style data structure. Namespaces are required by JSession and by default all values are retrieved from the default namespace. To get a value from a different namespace, we use the optional third JSession::get() parameter. $value = $session->get('hideAnnouncements', $defaultValue, 'mynamespace'); It is possible to store objects in the session. However, these require special attention when we extract them from the session. For more information about storing objects in the session, refer to the previous recipe, Adding data to the session. There's more... There is an alternative way of getting data from the session. User state data is also part of the session. The user state data allows us to store session data using more complex hierarchical namespaces, for example com_myextension.foo.bar.baz. To access user state data, we use the application object instead of the session handler. // get the application (this is the same as $mainframe)$app =& JFactory::getApplication();// get some user state data$value = $app->getUserState('com_myextsion.foo.bar.baz'); User state data is usually combined with request data. For example, if we know the request may include a value that we want to use to update the user state data, we use the JApplication::getUserStateFromRequest() method. // get some user state data and update from request$value = $app->getUserStateFromRequest( 'com_myextsion.foo.bar.baz', 'inputName', $defaultValue, 'INTEGER'); The four parameters we provide this method with are the path to the value in the state data, the name of the request input from which we want to update the value, the default value (which is used if there is no value in the request), and the type of value. This method is used extensively for dealing with display state data, such as pagination. // get global default pagination limit$defaultListLimit = $app->getCfg('list_limit');// get limit based on user state data / request data$limit = $app->getUserStateFromRequest( 'global.list.limit', 'limit', $defaultListLimit, 'INTEGER'); See also For information about setting values in the session, refer to the previous recipe, Adding data to the session.
Read more
  • 0
  • 0
  • 3337
Modal Close icon
Modal Close icon