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-competitive-service-and-contract-management-sap-business-one-implementation-part-1
Packt
16 Oct 2009
5 min read
Save for later

Competitive Service and Contract Management in SAP Business ONE Implementation: Part 1

Packt
16 Oct 2009
5 min read
What we will learn in this article? In this article, we will cover the service module and highlight how it fits in with the sales and opportunities management functionality. The key features, from taking a service call to contracting management, will be explained. In order to establish a practical platform for this, a case study will be expanded to utilize the service module. As a part of this section, a complete workflow will be configured from setting the right parameters in the admin section to connecting the information for service personnel. We will learn about : Key terms - The common terminology related to service management will be covered. There is nothing major waiting for you here. We will simply learn what the terms entail with regards to the SAP system. Service module core functions – In this section, the available functions and features will be put into perspective—what is available and how much we can expect from it. For example, you will learn what service operations mean. Case study and your own project – The available features of the service module will then be implemented for the case study. By doing so, knowledge will be provided to implement the service module in your own business. We will review some guidelines which will enable you to translate the case study implementation into a set of activities for your own project. Key terms Let's start with the key terms related to service and contract management in SAP Business ONE. By looking at the key terms, you will get an understanding of what can be accomplished with this module Service contract templates In the admin section, we can define the service contract templates that can later be used as a basis for actual contracts. Please note the template character. All of the parameters we define here will automatically populate the relevant details in the contract once a template is selected. The following screenshot shows that a contract template can be created not only on a per-customer basis, but also for item groups, and a specific item based on serial numbers. In addition, please note the Reminder setting. You can set a reminder which will provide an alert prior to the expiry of the contract. This way, you can be sure that you contact all customers and allow them to renew their contracts. Serial number contract The most common usage may be the Serial Number contract type. Each product will have a specific contractual service eligibility based on the serial number. Consequently, if a customer purchases an item that is managed by a serial number, a warranty contract template can be associated. This will create a customer equipment card. Customer contract However, please note that this concept does not need to be used only for items and serial numbers. As you can see in the previous screenshot, we can create contract templates for customers and whole item groups. For the case study, I will use this concept to create a service contract for key customers. We can then use the service functionality in SAP to make sure these customers get priority treatment. You see, we can use the service functionality in this creative way to improve our service quality. Item group contract Just as we may decide to use the service module to guarantee a specific response time to customers, we can make sure that a specific product line is managed. For example, if you have a new specifi c product line that requires technical expertise for implementation, then a service contract may be offered to customers. Therefore, all customers who purchase an item that belongs to this group will be eligible to purchase a contract and receive the relevant expert support. Customer equipment card The customer equipment card applies to the contracts that are managed by a serial number. Since the serial number contract applies a unique contract situation for each item, you will need to have the relevant information to be able to categorize a service call. For example, you need to know the serial number to identify the customer and the relevant warranty that remains for the specific serial number. In addition, if a customer calls you, you"ll want to be able to look up all of the serial numbers for this customer. This can be done using the customer equipment card. Please note that a customer equipment card is automatically created if a customer purchases an item that is managed by a serial number. You can assign a service contract when this happens on the level of sales order. Service calls Service calls are incoming service requests from business partners. The following screenshot shows that service calls can have many sources. For example, service calls may come via emails, phone calls, web requests, or any other defined Origin. I am highlighting this because, in essence, you can use the service module for any activity where you want to apply a specifi c response time management. Queues As mentioned above, the service module can be used to manage any kind of service-related activity. Queues allow your personnel to be associated with named groups. In the following screenshot, I have created two queues. The first queue is for 1st Level and the second queue for Resolution and Sales. Consequently, I assign personnel who can best accomplish the relevant tasks to each queue as follows: Knowledge base As you work on service calls, you can build a knowledge base that documents how problems were resolved. For example, if the problem resolution department resolved a problem, it will be documented as a part of the service call. If the service call is for a serialized item, then this knowledge is available to the first-level support the next time a problem is reported for the same item type. Therefore, this can take the workload off of the specialized personnel as they can avoid repetitive tasks. In addition, new employees can benefit from the knowledge already acquired for resolved service calls.
Read more
  • 0
  • 0
  • 6105

article-image-storing-planning-data-ibm-cognos-d-cube-part-1
Packt
16 Oct 2009
10 min read
Save for later

Storing Planning Data in IBM Cognos: D-Cube (Part 1)

Packt
16 Oct 2009
10 min read
Overview of the D-Cube In Analyst, data is stored in a D-Cube. The D-Cube is a multi-dimensional data structure similar to an OLAP or Excel pivot table. Each of the dimensions contains a list of related data. For example, in a four dimensional cube, the first dimension may contain the items in  P&L statement, the second may list the departments, the third show the timescale, and the fourth may show the version (Budget or Actual). In this example, you have the  P&L statement by month, by department, and by version. The D-Cube must have at least two dimensions. If more than two dimensions exist, the other dimensions appear as pages. The following screenshot depicts a four dimensional D-Cube. The first two dimensions form the rows and columns. The third and fourth dimensions are displayed as pages, in the upper-left corner of the D-Cube. You can switch to different pages in the cube by clicking the page drop-down list and selecting another page. Creating a D-Cube Creating a D-Cube takes a few simple steps but it requires a great deal of forethought. Before creating the D-Cube, you must think through the dimensions that will form the cube. You must know what data will populate the D-Cube. You must know what category of D-Lists your selection falls under so that you can prioritize the calculations appropriately. You must know what function the D-Cube performs. Is it an input cube, a calculation cube, a summary or reporting cube, or a staging cube? You must also know in which library the D-Cube will be stored, and whether the D-Cube will be shared or will be exclusive to a model. Finally, you must consider size and performance, especially if you plan to deploy the D-Cube in Contributor. To create a D-Cube: Click on File | New | D-Cube. In the Create new D-Cube box, select the D-List that makes up the D-Cube. Drop the D-List onto the lower pane. Order the D-List. Click on OK. Enter the D-Cube name, and then click on OK. By default, the D-Cube opens with the longest D-List as the rows and the timescale as the columns. You can transpose the cube or swap the dimensions by dragging and dropping them. When you close and reopen the D-Cube, it will revert to the default view. Order of dimensions It is important to have the proper order of dimensions in the D-Cube. The order of dimensions is important because it determines which calculation takes precedence when calculations from two separate D-Lists intersect. The order also determines the priority of formats when the cell has opposing formats. As a rule, the dimensions must follow this order: Calculation: Calculation D-Lists contain mathematical operations over and above simple addition. Any use of operators, such as multiplication, subtraction, division, or the use of a BiF, make the D-List a calculation D-List. Aggregation: Aggregation D-Lists usually contain a hierarchy of items, such as an organizational hierarchy, a list of products, customers, or cost centers, or a list of items with a simple subtotal. Non-Calculating: Non-Calculating D-Lists contain no calculations. Timescale: Timescale D-Lists contains items that span a period of time, such as months, weeks, or days. Versions: Version D-Lists contain iterations of the data, such as Actual, Budget, Forecast, and Revised Budget. It is critical to set the proper order of dimensions before building the Contributor application. If you reorder the dimensions after the application is created, all of the data in the D-Cube will be deleted. In addition, reordering dimensions changes the structure of the import tables and, therefore, the way that you import data into Contributor. Size considerations The size of the D-Cube is measured by the number of cells in it. The number of cells you can have in a D-Cube is limited only by your computer's memory. When you build a D-Cube, you should keep in mind the amount of memory available on the computer on which the model will be used. You will not be able to open a large cube if your PC does not have enough memory to handle the data. If the model is deployed in Contributor, size is an even more important consideration. Even with a powerful computer, you will experience performance lag because a large model must pass through the organization's network. In a wide area network, the problem associated with a large model becomes more apparent. To determine the number of cells, find the product of the number of items in all of the D-lists in the D-Cube. For instance, if a D-Cube has five D-Lists, which have the following number of items: 8, 1, 10, 5, and 12, the number of cells in the D-Cube will be 4,800. This is 8*1*10*5*12. You can find the number of cells in the dimension selection box, as illustrated in the following screenshot: The number of items in a dimension has an inverse impact on the magnitude of size increases for additions to the cube. The fewer the items, the bigger the impact that an addition will have to the size of the cube. In the example of the cube above, if you add one item to a dimension that has only one item, you will double the size of the cube. However, if you add one item to a dimension that has 10 items, you will increase the size of the cube by only ten percent. One clue that your D-Cube may have a problem with size is the number of dimensions. While there is no limitation on the number of dimensions that a cube can have, having too many of them can become a problem. With a D-Cube that has too many dimensions, any additional item in one of the D-Lists increases the size in an order of magnitude depending on the number of items in the D-List. If possible, keep the number of dimensions to not more than five. If you need to have a D-Cube that provides views of data beyond five dimensions, consider splitting the D-Cube. You are more likely to require less memory if you have several smaller cubes than with one super cube. With Analyst, you can open a D-Cube that has several million cells on a PC that has 512MB of RAM. However, if you plan to deploy the model in Contributor, the threshold for the number of cells is much lower. An acceptable benchmark is roughly 500,000 cells per e.List. This benchmark is subject to many other factors, such as network latency, client PC memory, and CPU, all of which can contribute to model performance. Working with the D-Cube When working with the D-Cube, you have several functionalities that help you to hone in on the information that you want. By default, the D-Cube opens in full view, but you can open only a slice of the cube and save the slice for later viewing. Opening a full view of the D-Cube The most straightforward way to view the D-Cube is to open all dimensions. To open a full D-Cube: Click on File | Open | D-Cube. Select the D-Cube. Click on OK. Select the Full option. Click on OK. Opening a selection of the D-Cube A selection is a subset of a D-Cube. You can only open the specific items of the dimensions that you want to view. Because the data in a selection is fewer than the full view, less memory is required and the D-Cube opens and recalculates faster. To open a selection of the D-Cube: Click on File | Open | D-Cube. Select the D-Cube. Click on OK. Select the Edit Selection option. This option opens the dimension selection box, where you can select the items that you want to view in the D-Cube slice. As shown in the following illustration, the item selection box lets you select the items from a dimension that you want to include in your view. In the item selection box, each tab represents a D-List. To select the items, move the items from the Items available pane (on the left) to the Items included pane (on the right). Click on OK. Viewing different slices of the D-Cube You can view the D-Cube in a variety of ways. You can open a selection of the D-Cube, or several selections at the same time. If you have a selection open, you can change it to another selection. The ability to switch views makes it easier to work with the D-Cube. For instance, suppose you have a D-Cube that has two versions: Budget and Actual. If you want to enter only budget data, you may want to open only the Budget dimension and keep the Actual dimension closed. You can have multiple selections of the D-Cube open at the same time in the same way that you open the D-Cube. This allows you to arrange the selections next to each other on the same screen. To modify the views of the D-Cube: With the D-Cube open, click on D-CubeSelections: New Slice: This option allows you to create a new view of the same D-Cube, with the same selection. Reselect: Modify the current selection. Selecting this option allows you to add or remove dimensions in the current view. Save: Save the current selection as a saved selection. This option allows you to save the current view so that you can open it again later. If you select Reselect, move the items that you want to add to or remove from the current view from the Items included to the Items available pane, or vice versa, respectively. Click on OK. Saving a selection You can select a view of a D-Cube and then save this selection so that you do not have to reselect the same view the next time that you open the cube. When you save a selection, you create a "saved selection"—an object that is derived from the cube. To save a selection: Click File | Open | D-Cube. Select the D-Cube. Under Mode, select Edit Selection. Select the D-List items that you want to view in the D-Cube, and move them from the Items available pane to the Items included pane. If you do not select anything in the Items available pane, then all of the items will be included in the selection, including any future additions to the D-List. Under the Save Selections option on the lower-right corner of the dialog box, click on the Save button. Enter the name of the saved selection. Click on OK. If you have a saved selection, you can load it into the item selection box. The dimension item selection box is used in many functions, including export, D-List imports, and D-Cube allocations (to be discussed later). Opening the saved selection Once saved, the selection becomes a separate object that can be copied and shared. However, because it is a subset of the cube, you have to go through the cube to access the saved selection. To open the saved selection: Click on File | Open | D-Cube. Select the D-Cube. Under Mode, select Saved Selection. Select the Saved Selection. Click on OK    
Read more
  • 0
  • 0
  • 2375

article-image-jbi-binding-components-netbeans-ide-6
Packt
16 Oct 2009
4 min read
Save for later

JBI Binding Components in NetBeans IDE 6

Packt
16 Oct 2009
4 min read
Binding Components Service Engines are pluggable components which connect to the Normalized Message Router (NMR) to perform business logic for clients. Binding components are also standard JSR 208 components that plug in to NMR and provide transport independence to NMR and Service Engines. The role of binding components is to isolate communication protocols from JBI container so that Service Engines are completely decoupled from the communication infrastructure. For example, BPEL Service Engine can receive requests to initiate BPEL process while reading files on the local file system. It can receive these requests from SOAP messages, from a JMS message, or from any of the other binding components installed into JBI container. Binding Component is a JSR 208 component that provides protocol independent transport services to other JBI components. The following figure shows how binding components fit into the JBI Container architecture: In this figure, we can see that the role of BC is to send and receive messages both internally and externally from Normalized Message Router using protocols, specific to the binding component. We can also see that any number of binding components can be installed into the JBI container. This figure shows that like Service Engines (SE), binding components do not communicate directly with other binding components or with Service Engines. All communication between individual binding components and between binding components and Service Engines is performed via sending standard messages through the Normalized Message Router. NetBeans Support for Binding Components The following table lists which binding components are installed into the JBI container with NetBeans 5.5 and NetBeans 6.0:   As is the case with Service Engines, binding components can be managed within the NetBeans IDE. The list of Binding Components installed into the JBI container can be displayed by expanding the Servers | Sun Java System Application Server 9 | JBI | Binding Components node within the Services explorer. The lifecycle of binding components can be managed by right-clicking on a binding component and selecting a lifecycle process—Start, Stop, Shutdown, or Uninstall. The properties of an individual binding component can also be obtained by selecting the Properties menu option from the context menu as shown in the following figure. Now that we've discussed what binding components are, and how they communicate both internally and externally to the Normalized Message Router, let's take a closer look at some of the more common binding components and how they are accessed and managed from within the NetBeans IDE. File Binding Component The file binding component provides a communications mechanism for JBI components to interact with the file system. It can act as both a Provider by checking for new files to process, or as a Consumer by outputting files for other processes or components. The figure above shows the file binding component acting as a Provider of messages. In this scenario, a message has been sent to the JBI container, and picked up by a protocol-specific binding component (for example, a SOAP message has been received). A JBI Process then occurs within the JBI container which may include routing the message between many different binding components and Service Engines depending upon the process. Finally, after the JBI Process has completed, the results of the process are sent to File Binding Component which writes out the result to a file. The figure above shows the file binding component acting as a Consumer of messages. In this situation, the File Binding Component is periodically polling the file system looking for files with a specified filename pattern in a specified directory. When the binding component finds a file that matches its criteria, it reads in the file and starts the JBI Process, which may again cause the input message to be routed between many different binding components and Service Engines. Finally, in this example, the results of the JBI Process are output via a Binding Component. Of course, it is possible that a binding component can act as both a provider and a consumer within the same JBI process. In this case, the file binding component would be initially responsible for reading an input message from the file system. After any JBI processing has occurred, the file binding component would then write out the results of the process to a file. Within the NetBeans Enterprise Pack, the entire set of properties for the file binding component can be edited within the Properties window. The properties for the binding component are displayed when either the input or output messages are selected from the WSDL in a composite application as shown in the following figure.
Read more
  • 0
  • 0
  • 1826

article-image-building-facebook-application-part-2
Packt
16 Oct 2009
11 min read
Save for later

Building a Facebook Application: Part 2

Packt
16 Oct 2009
11 min read
Mock AJAX and your Facebook profile I'm sure that you've heard of AJAX (Asynchronous JavaScript and XML) with which you can build interactive web pages. Well, Facebook has Mock AJAX, and with this you can create interactive elements within a profile page. Mock AJAX has three attributes that you need to be aware of: clickwriteform: The form to be used to process any data. clickwriteid: The id of a component to be used to display our data. clickwriteurl: The URL of the application that will process the data. When using Mock AJAX, our application must do two things: Return the output of any processed data (and we can do that by using either echo or print). Define a form with which we'll enter any data, and a div to receive the processed data Using a form on your profile Since we want to make our application more interactive, one simple way is to add a form. So, for our first example we can add a function (or in this case a set of functions) to appinclude.php that will create a form containing a simple combo-box: function country_combo () {/*You use this function to display a combo-box containing a list of countries. It's in its own function so that we can use it in other forms without having to add any extra code*/$country_combo = <<<EndOfText<select name=sel_country><option>England</option><option>India</option></select>EndOfText;return $country_combo;}function country_form () {/*Like country_combo-box we can use this form where ever needed because we've encapsulated it in its own function */global $appcallbackurl;$country_form = "<form>";$country_form .= country_combo ();$country_form .= <<<EndOfText<input type="submit" clickrewriteurl="$appcallbackurl" clickrewriteid="info_display" value="View Country"/><div id="info_display" style="border-style: solid; border-color: black; border-width: 1px; padding: 5px;">No country selected</div></form>EndOfText;return $country_form;}function display_simple_form () {/*This function displays the country form with a nice subtitle (on the Profile page)*/global $facebook, $_REQUEST;#Return any processed dataif (isset($_REQUEST['sel_country'])) { echo $_REQUEST['sel_country'] . " selected"; exit;}#Define the form and the div$fbml_text = <<<EndOfText<fb:subtitle><fb:name useyou=false uid=$user firstnameonly=true possessive=true> </fb:name> Suspect List</fb:subtitle>EndOfText;$fbml_text .= country_form ();$facebook->api_client->profile_setFBML($fbml_text, $user);echo $fbml_text;} And, of course, you'll need to edit index.php: display_simple_form (); You'll notice from the code that we need to create a div with the id info_display, and that this is what we use for the clickrewriteid of the submit button. You'll also notice that we're using $appcallbackurl for the clickrewriteurl ($appcallbackurl is defined in appinclude.php). Now, it's just a matter of viewing the new FMBL (by clicking on the application URL in the left-navigation panel): If you select a country, and then click on View Country, you'll see: I'm sure that you can see where we're going with this. The next stage is to incorporate this form into our Suspect Tracker application. And the great thing now is that because of the functions that we've already added to appinclude.php, this is now a very easy job: function first_suspect_tracker () {global $facebook, $_REQUEST;if (isset($_REQUEST['sel_country'])) { $friend_details = get_friends_details_ by_country ($_REQUEST['sel_country']); foreach ($friend_details as $friend) { $div_text .= "<fb:name uid=" . $friend['uid'] . " firstnameonly=false></fb:name>, "; } echo $div_text; exit;}$fbml_text .= country_form ();$facebook->api_client->profile_setFBML($fbml_text, $user);$facebook->redirect($facebook->get_facebook_url() . '/profile.php');} You may also want to change the country_form function, so that the submit button reads View Suspects. And, of course, we'll also need to update index.php. Just to call our new function: <?phprequire_once 'appinclude.php';first_suspect_tracker ();?> This time, we'll see the list of friends in the selected country: or: OK, I know what you're thinking, this is fine if all of your friends are in England and India, but what if they're not? And you don't want to enter the list of countries manually, do you? And what happens if someone from a country not in the list becomes your friend? Obviously, the answer to all of these questions is to create the combo-box dynamically. Creating a dynamic combo-box I'm sure that from what we've done so far, you can work out how to extract a list of countries from Facebook: function country_list_sql () {/*We're going to be using this piece of SQL quite often so it deserves its own function*/global $user;$country_list_sql = <<<EndSQLSELECT hometown_location.countryFROM userWHERE uid IN (SELECT uid1FROM friendWHERE uid2=$user)EndSQL;return $country_list_sql;}function full_country_list () {/*With the SQL in a separate function this one is very short and simple*/global $facebook;$sql = country_list_sql ();$full_country_list = $facebook-> api_client->fql_query($sql);print_r ($full_country_list);} However, from the output, you can see that there's a problem with the data: If you look through the contents of the array, you'll notice that some of the countries are listed more than once—you can see this even more clearly if we simulate building the combo-box: function options_country_list () {global $facebook;$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);foreach ($country_list as $country){ echo "option:" . $country['hometown_location']['country'] ."<br>";}} From which, we'd get the output: This is obviously not what we want in the combo-box. Fortunately, we can solve the problem by making use of the array_unique method, and we can also order the list by using the sort function: function filtered_country_list () {global $facebook;$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);$combo_full = array();foreach ($country_list as $country){ array_push($combo_full, $country['hometown_location']['country']);}$combo_list = array_unique($combo_full);sort($combo_list);foreach ($combo_list as $combo){ echo "option:" . $combo ."<br>";}} And now, we can produce a usable combo-box: Once we've added our code to include the dynamic combo-box, we've got the workings for a complete application, and all we have to do is update the country_combo function: function country_combo () {/*The function now produces a combo-box derived from the friends' countries */global $facebook;$country_combo = "<select name=sel_country>";$sql = country_list_sql ();$country_list = $facebook->api_client->fql_query($sql);$combo_full = array();foreach ($country_list as $country){ array_push($combo_full, $country['hometown_location']['country']);}$combo_list = array_unique($combo_full);sort($combo_list);foreach ($combo_list as $combo){ $country_combo .= "<option>" . $combo ."</option>";}$country_combo .= "</select>";return $country_combo;} Of course, you'll need to reload the application via the left-hand navigation panel for the result: Limiting access to the form You may have spotted a little fly in the ointment at this point. Anyone who can view your profile will also be able to access your form and you may not want that (if they want a form of their own they should install the application!). However, FBML has a number of if (then) else statements, and one of them is <fb:if-is-own-profile>: <?phprequire_once 'appinclude.php';$fbml_text = <<<EndOfText<fb:if-is-own-profile>Hi <fb:name useyou=false uid=$user firstnameonly=true></fb:name>, welcome to your Facebook Profile page.<fb:else>Sorry, but this is not your Facebook Profile page - it belongs to <fb:name useyou=false uid=$user firstnameonly=false> </fb:name>,</fb:else></fb:if-is-own-profile>EndOfText;$facebook->api_client->profile_setFBML($fbml_text, $user);echo "Profile updated";?> So, in this example, if you were logged on to Facebook, you'd see the following on your profile page: But anyone else viewing your profile page would see: And remember that the FBML is cached when you run: $facebook->api_client->profile_setFBML($fbml_text, $user); Also, don't forget, it is not dynamic that is it's not run every time that you view your profile page. You couldn't, for example, produce the following for a user called Fred Bloggs: Sorry Fred, but this is not Your Facebook Profile page - it belongs to Mark Bain That said, you are now able to alter what's seen on the screen, according to who is logged on. Storing data—keeping files on your server From what we've looked at so far, you already know that you not only have, but need, files stored on your server (the API libraries and your application files). However, there are other instances when it is useful to store files there. Storing FBML on your server In all of the examples that we've worked on so far, you've seen how to use FBML mixed into your code. However, you may be wondering if it's possible to separate the two. After all, much of the FBML is static—the only reason that we include it in the code is so that we can produce an output. As well as there may be times when you want to change the FBML, but you don't want to have to change your code every time you do that (working on the principle that the more times you edit the code the more opportunity there is to mess it up). And, of course, there is a simple solution. Let's look at a typical form: <form><div id="info_display" style="border-style: solid; border-color: black; border-width: 1px; padding: 5px;"></div><input name=input_text><input type="submit" clickrewriteurl="http://213.123.183.16/f8/penguin_pi/" clickrewriteid="info_display" value="Write Result"></form> Rather than enclosing this in $fbml_text = <<<EndOfText ... EndOfText; as we have done before, you can save the FBML into a file on your server, in a subdirectory of your application. For example /www/htdocs/f8/penguin_pi/fbml/form_input_text.fbml. "Aha" I hear your say, "won't this invalidate the caching of FBML, and cause Facebook to access my server more often than it needs?" Well, no, it won't. It's just that we need to tell Facebook to update the cache from our FBML file. So, first we need to inform FBML that some external text needs to be included, by making use of the <fb:ref> tag, and then we need to tell Facebook to update the cache by using the fbml_refreshRefUrl method: function form_from_server () {global $facebook, $_REQUEST, $appcallbackurl, $user;$fbml_file = $appcallbackurl . "fbml/form_input_text.fbml";if (isset($_REQUEST['input_text'])) { echo $_REQUEST['input_text']; exit;}$fbml_text .= "<fb:ref url='" . $fbml_file . "' />";$facebook->api_client->profile_setFBML($fbml_text, $user);$facebook->api_client->fbml_refreshRefUrl($fbml_file);echo $fbml_text;} As far as your users are concerned, there is no difference. They'll just see another form on their profile page: Even if your users don't appreciate this leap forward, it will make a big difference to your coding—you're now able to isolate any static FBML from your PHP (if you want). And now, we can turn our attention to one of the key advantages of having your own server—your data. Storing data on your server So far, we've concentrated on how to extract data from Facebook and display it on the profile page. You've seen, for example, how to list all of your friends from a given country. However, that's not how Pygoscelis' list would work in reality. In reality, you should be able to select one of your friends and add them to your suspect list. We will, therefore, spend just a little time on looking at creating and using our own data. We're going to be saving our data in files, and so your first job must be to create a directory in which to save those files. Your new directory needs to be a subdirectory of the one containing your application. So, for example, on my Linux server I would do: cd /www/htdocs/f8/penguin_pi       #Move to the application directory mkdir data #Create a new directory chgrp www-data data                          #Change the group of the directory chmod g+w data                                  #Ensure that the group can write to data
Read more
  • 0
  • 0
  • 2555

article-image-posting-your-wordpress-blog
Packt
16 Oct 2009
12 min read
Save for later

Posting on Your WordPress Blog

Packt
16 Oct 2009
12 min read
The central activity you'll be doing with your blog is adding posts. A post is like an article in a magazine; it's got a title, content, and an author (you). If a blog is like an online diary, then every post is an entry in that diary. A blog post also has a lot of other information attached to it, such as a date and categories. In this article, you will learn how to create a new post and what kind of information you can attach to it. Adding a simple post Let's review the process of adding a simple post to your blog. Whenever you want to do maintenance on your WordPress website, you have to start by logging in to the WP Admin (WordPress Administration panel) for your site. To get to the admin panel, just point your web browser to http://yoursite.com/wp-admin. Remember that if you have installed WordPress in a subfolder (for example, blog), then your URL has to include the subfolder (that is, http://yoursite.com/blog/wp-admin). When you first log into the WP Admin, you'll be at the Dashboard. The Dashboard has a lot of information on it. The very top bar, which I'll refer to as the top menu, is mostly dark grey and on the left, of course, is the main menu. The top menu and the main menu exist on every page within the WP Admin. The main section on the right contains information for the current page you're on. In this case, we're on the Dashboard. It contains boxes that have a variety of information about your blog, and about WordPress in general. The quickest way to get to the Add New Post page at any time is to click on the New Post link at the top of the page in the top bar (top menu). This is the Add New Post page: To quickly add a new post to your site, all you have to do is: Type in a title into the text field under Add New Post (for example, Making Lasagne). Type the text of your post in the content box. Note that the default view is Visual, but you actually have a choice of the HTML view as well. Click on the Publish button, which is at the far right. Note that you can choose to save a draft or view a preview of your post. In the following image, the title field, the content box, and the Publish button of the Add New Post page are highlighted: Once you click on the Publish button, you have to wait while WordPress performs its magic. You'll see yourself still on the Edit Post page, but now the following message has appeared telling you that your post was published and giving you a link to View post: If you go to the front page of your site, you'll see that your new post has been added at the top (newest posts are always at the top): Common post options Now that we've reviewed the basics of adding a post, let's investigate some of the other options on the Add New Post page. In this section we'll look at the most commonly used options, and in the next section we'll look at the more advanced options. Categories and tags Categories and tags are two similar types of information that you can add to a blog post. We use them to organize the information in your blog by topic and content (rather than just by, say, date), and to help visitors find what they are looking for on your blog. Categories are primarily used for structural organizing. They can be hierarchical. A relatively busy blog will probably have at least 10 categories, but probably not more than 15 or 20. Each post in this blog will likely have one to four categories assigned to it. For example, a blog about food might have these categories: Cooking Adventures, In The Media, Ingredients, Opinion, Recipes Found, Recipes Invented, and Restaurants. Tags are primarily used as shorthand for describing the topics covered in a particular blog post. A relatively busy blog will have anywhere from 15 to 30 tags in use. Each post in this blog will likely have three to ten tags assigned to it. For example, a post on the food blog about a recipe for butternut squash soup may have these tags: soup, vegetarian, autumn, hot, easy. Let's add a new post to the blog. This time, we'll give it not only a title and content, but also tags and categories. When adding tags, just type your list of tags into the Tags box on the right, separated by commas: Then click on the Add button. The tags you just typed in will appear below the text field with little xs next to them. You can click on an x to delete a tag. Once you've used some tags in your blog, you'll be able to click on the Choose from the most popular tags link in this box so that you can easily re-use tags. Categories work a bit differently than tags. Once you get your blog going, you'll usually just check the boxes next to existing categories in the Categories box. In this case, as we don't have any existing categories, we'll have to add one or two. In the Categories box on the right, click on the + Add New Category link. Type your category into the text field and click on the Add button. Your new category will show up in the list, already checked. Look at the following screenshot: If in the future you want to add a category that needs a parent category, select Parent category from the pull-down menu before clicking on the Add button. If you want to manage more details about your categories, move them around, rename them, assign parent categories, and assign descriptive text. You can do this on the Categories page, which we'll see in detail later in this article. Now fill in your title and content here: Click on the Publish button and you're done. When you look at the front page of your site, you'll see your new post on the top, your new category in the sidebar, and the tags and category (that you chose for your post) listed under the post itself: Adding an image to a post You may often want to have an image show up in your post. WordPress makes this very easy. Let's add an image to the post we just created. You can click on Edit underneath your post on the front page of your site to get there quickly. Alternatively, go back to the WP Admin, open Posts in the main menu, and then click on Edit underneath your new post. To add an image to a post, first you'll need to have that image on your computer. Before you get ready to upload an image, make sure that your image is optimized for the Web. Huge files will be uploaded slowly and slow down the process of viewing your site. You can re-size and optimize images using software such as GIMP or Photoshop. For the example in this article, I have used a photo of butternut squash soup that I have taken from the website where I got the recipe, and I know it's on the desktop of my computer. Once you have a picture on your computer and know where it is, follow these steps to add the photo to your blog post: Click on the little photo icon, which is next to the word Upload/Insert and below the box for the title: In the box that appears, click on the Select Files button and browse to your image. Then click on Open and watch the uploader bar. When it's done, you'll have a number of fields you can fill in: The only fields that are important right now are Title, Alignment, and Size. Title is a description for the image, Alignment will tell the image whether to have text wrap around it, and Size is the size of the image. As you can see, I've chosen the Right alignment and the Thumbnail size. Now click on Insert into Post. This box will disappear, and your image will show up in the post on the edit page itself: Now click on the Update Post button and go look at the front page of your site again. There's your image! You may be wondering about those image sizes. What if you want bigger or smaller thumbnails? You can set the pixel dimensions of your uploaded images and other preferences by opening Settings in the main menu and then clicking on Media. This takes you to the Media Settings page: Here you can specify the size of the uploaded images for: Thumbnail Medium Large If you change the dimensions on this page and click on the Save Changes button, only images you upload in the future will be affected. Images you've already uploaded to the site will have had their thumbnail, medium, and large versions created already using the old dimensions. Using the Visual editor versus the HTML editor WordPress comes with a Visual editor, otherwise known as a WYSIWYG editor (pronounced wissy-wig, which stands for What You See Is What You Get). This is the default editor for typing and editing your posts. If you're comfortable with HTML, you may prefer to write and edit your posts using the HTML editor—particularly useful if you want to add special content or styling. To switch from the rich text editor to the HTML editor, click on the HTML tab next to the Visual tab at the top of the content box: You'll see your post in all its raw HTML glory and you'll get a new set of buttons that lets you quickly bold and italicize text as well as add link code, image code, and so on. You can make changes and swap back and forth between the tabs to see the result. If you want the HTML tab to be your default editor, you can change this on your Profile page. Navigate to Users | Your Profile, and select the Disable the visual editor when writing checkbox. Drafts, timestamps, and managing posts There are three additional, simple but common, items I'd like to cover in this section: drafts, timestamps, and managing posts. Drafts WordPress gives you the option to save a draft of your post so that you don't have to publish it right away but can still save your work. If you've started writing a post and want to save a draft, just click on the Save Draft button at the right (in the Publish box), instead of the Publish button. Even if you don't click on the Save Draft button, WordPress will attempt to save a draft of your post for you about once a minute. You'll see this in the area just below the content box. The text will say Saving Draft... and then the time of the last draft saved: At this point, after a manual save or an auto-save, you can leave the Edit Post page and do other things. You'll be able to access all of your draft posts from the Dashboard or from the Edit Posts page. Timestamps WordPress will also let you alter the timestamp of your post. This is useful if you are writing a post today that you wish you'd published yesterday, or if you're writing a post in advance and don't want it to show up until the right day. The default timestamp will always be set to the moment you publish your post. To change it, just find the Publish box and click on the Edit link (next to the calendar icon and Publish immediately), and fields will show up with the current date and time for you to change: Change the details, click on the OK button, and then Publish your post (or save a draft). Managing posts If you want to see a list of your posts so that you can easily skim and manage them, you just need to go to the Edit Posts page in the WP Admin by navigating to Posts in the main menu. You'll see a detailed list of your posts, as seen in the next screenshot: There are so many things you can do on this page! You can: Choose a post to edit—click on a post title and you'll go back to the main Edit Post page Quick-edit a post—click on the Quick Edit link for any post and new options will appear right in the list, which will let you edit the title, timestamp, categories, tags, and more Delete one or more posts—click on the checkboxes next to the posts you want to delete, choose Delete from the Bulk Actions drop-down menu at the bottom, and click on the Apply button Bulk edit posts—choose Edit from the Bulk Actions menu at the bottom, click on the Apply button, and you'll be able to assign categories and tags to multiple posts, as well as edit other information about them You can experiment with the other links and options on this page. Just click on the pull-down menus and links, and see what happens.
Read more
  • 0
  • 0
  • 8869

article-image-maintaining-optimizing-and-upgrading-your-site-drupal-6-part-2
Packt
16 Oct 2009
9 min read
Save for later

Maintaining, Optimizing and Upgrading Your Site in Drupal 6: Part 2

Packt
16 Oct 2009
9 min read
Maintaining content As you continue to add content to your web site, you will need to ensure that your content is properly moderated, that old content is removed, and that changes to web site content are tracked. Creating content revisions Good Eatin' Goal: Create revisions of content to ensure that you have a complete record of changes to your web site's content. Additional modules needed: None. Basic steps We have simply updated our pages as necessary to add new functionality and content. However, if you have many editors, content that changes frequently, a need to view the history of a page, or need the ability to easily return to an old version of a page, you will want to store multiple revisions of your pages. To do this, carry out the following steps: Edit the content for which you want to create a new revision. Make the changes as needed and, before saving, expand the Revision information section. Select the Create new revision option and enter a message describing the changes that you have made to the node. When you save the content, you will see a new tab called Revisions. Clicking on this tab will show you a list of all of the revisions that have been created for the page. If you would like to return to an older version of the page, you can click the revert link. Or, if you want to remove an older revision, you can click the delete link to get rid of it permanently. You can control which users have access to the revision system by using the Permissions Manager. Drupal allows you to control which users can: view revisions, revert revisions, and delete revisions. If you want to force users to always create new revisions when editing content, edit the content type and then expand the Workflow settings. Change the default options to select the Create new revision option. When editors change content, the Create new revision option will be selected by default, and they will not be able to change the option unless they have the administer nodes permission. If you want to approve all revisions before publication, you can deselect the Published checkbox. Comparing content revisions Good Eatin' Goal: Compare the text of two different revisions of a page. Additional modules needed: Diff (http://drupal.org/project/diff). Basic steps Although the built-in functionality for creating revisions in Drupal works perfectly well, it can be difficult to review the changes that were made in each revision. The Diff module makes comparing revisions very easy. Begin by installing and activating the Diff module. To use the Diff module, simply view the revisions for any page. You will notice that the Revisions list has changed to allow you to select the revisions to be compared. Select the revisions to compare and then click on the Show diff button. Drupal will then display information about the text that has been changed, added, or deleted. Moderate content Good Eatin' Goal: Find questionable or offensive content, and remove it from your site, easily. Additional modules needed: Modr8 (http://drupal.org/project/modr8). Basic steps An unfortunate side effect of having a web site on the Internet is that, at some point, a malicious user will attempt to post inappropriate content on your site. If your site is extremely busy, you may find yourself with a large amount of content to review and approve. The Modr8 module can help you manage the workload and can send emails to users letting them know when their content has been approved or rejected. Begin by installing and activating the Modr8 module. The settings for the Modr8 module can be accessed by selecting Site configuration and then Modr8, from the Administer menu. The basic settings control how often logs are removed. Alternatively, you can choose to keep the logs forever. You can also change the number of items in the moderation queue to be displayed at a time, as well as the default action for the content that requires moderation. You can also configure the email settings for the moderation queue, including the text of the emails, and whether or not emails should be sent to the user who posted the content when their content is approved and/or when their content is rejected. You can also choose to send an email if the moderator does not take action for the item and wants to send a note to the author. If you would like new content to be added to the moderation queue automatically, you can edit the content type and select the In moderation queue setting in the workflow section. To view the moderation queue, select Content management and then Moderated content, from the Administer menu. The moderation queue appears as follows: From this page, you can approve, delete, or defer action on any content that needs moderation. After you make your changes, click Save to complete your selections. You can also display a log of all the moderation actions, by clicking on Reports and then Content moderation log. The moderation log appears as follows: Allowing users to report questionable or offensive content. Good Eatin' Goal: Get feedback from users to learn what they find offensive so the objectionable content can be removed. Additional modules needed: Abuse (http://drupal.org/project/abuse). Basic steps In the last task, we reviewed methods that allowed you to moderate every piece of content that is added to the site. However, this can be a time-intensive task if the proportion of content that you receive that is questionable is low. If this is the case, you can allow your users to help you to moderate the content by using the Abuse module, to let them report items that they find offensive. This strategy has a couple of advantages. Firstly, you are freed from the maintenance of pre-approving all content before it is published. Secondly, it ensures that the content meets community standards, rather than placing you or your editors in charge of defining community standards. The Abuse module also has a Watchlist component that allows you to flag content as suspicious or banned, and automatically move them into a queue for review by an administrator. Begin by downloading and installing the Abuse and Watchlist modules, both of which are included in the Abuse installation. We will begin by editing the Watchlist settings, which can be accessed by selecting Site configuration and then Watchlist settings, from the Administer menu. You can include any words that you want to, in the Watch list and Filtered/banned word list, depending on your target audience and your site's needs; just make sure that you enter one word per line. Items on the Watch list can be viewed while they are in the review queue, and items on the Filtered/banned word list will be hidden until they are reviewed. You can also control which items are automatically added to the Watch list or banned list, based on the Watchlist word settings configured above. You can also force moderation for specific types if they are more prone to abuse. We can now modify the Abuse Moderation settings by selecting Site configuration and then Abuse Moderation settings, from the Administer menu. The first setting controls what content types are subject to abuse reports. The next section of controls how abuse tickets are to be handled by your moderators. If you have multiple moderators for your site, you can select the Abuse Assigned Moderators option. If you use this, you will also need to store the maximum number of items that have been flagged for abuse that are added to the moderator's queue. If moderators live in different time zones, you can set an hour of the day at which all moderation queues are cleared, so that items do not remain in the moderation queue for an overly-long period of time. Finally, you can configure the settings related to all of the items that have been flagged as abusive by a user. The Abuse threshold controls how many complaints must be registered for an item before it is moved into the moderation queue. 3 is a good number to start with, but you may want to increase or decrease the threshold depending on the needs of your site. You can edit the reasons for flagging an item for abuse by selecting Site configuration, then Abuse Moderation settings, and finally Abuse Moderation reasons, from the Administer menu. All available reasons will be listed on the page using a format similar to the example above. You can add new reasons, remove reasons, or change the text for reasons from this page. Before the abuse module is activated, you need to assign permissions to users, so that they can flag content for review. Content that has the abuse module activated will have a new Flag as offensive link added to it, as shown in the following screenshot: When the user clicks on the Flag as offensive link, he or she will be presented with a form where he or she can specify their contact information, and a reason why he or she believes that the content is offensive. Administrators can review content that has been flagged as offensive by clicking on Content management and then Moderate. The administrators can click on the Get More Tickets link to have additional items assigned to them. Once a ticket has been assigned to them, the administrator can view information about the user who submitted the content as well as the user who flagged the content, and choose what action to take for the content. The administrator can either allow the content, or remove the content from the web site. The administrator can also optionally send a warning to the user without further action.
Read more
  • 0
  • 0
  • 1795
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 €18.99/month. Cancel anytime
article-image-oracle-vm-management
Packt
16 Oct 2009
6 min read
Save for later

Oracle VM Management

Packt
16 Oct 2009
6 min read
Before we get to manage the VMs in the Oracle VM Manager, let's take a quick look at the Oracle VM Manager by logging into it. Getting started with Oracle VM Manager In this article, we will perform the following actions while exploring the Oracle VM Manager: Registering an account Logging in to Oracle VM Manager Create a Server Pool After we are done with the Oracle VM Manager installation, we will use one of the following links to log on to the Oracle VM Manager: Within the local machine: http://127.0.0.1:8888/OVS Logging in remotely: http://vmmgr:8888/OVS Here, vmmgr refers to the host name or IP address of your Oracle VM Manager host. How to register an account Registering of an account can be done in several ways. If, during the installation of Oracle VM Manager, we have chosen to configure the default admin account "admin", then we can use this account directly to log on to Oracle's IntraCloud portal we call Oracle VM Manager. We will explain later in detail about the user accounts and why we would need separate accounts for separate roles for fine-grained access control; something that is crucial for security purposes. So let's have a quick look at the three available options: Default installation: This option applies if we have performed the default installation ourselves and have gone ahead to create the account ourselves. Here we have the default administrator role. Request for account creation: Contacting the administrator of Oracle VM Manager is another way to attain an account with the privileges, such as administrator, manager, and user. Create yourself: If we need to conduct basic functions of a common user with operator's role such as creating and using virtual machines, or importing resources, we can create a new account ourselves. However, we will need the administrator to assign us the server pools and groups to our account before we can get started. Here by default we are granted a user role. We will talk more about roles later in this article. Now let's go about registering a new account with Oracle VM Manager. Once on the Oracle VM Manager Login page click on the Register link. We are presented with the following screen. We must enter a Username of our choice and a hard-to-crack password twice. Also, we have to fill in our First Name and Last Name and complete the registration with a valid email address. Click Next: Next, we need to confirm our account details by clicking on the Confirm button. Now our account will be created and a confirmation message is displayed on the Oracle VM Manager Login screen. It should be noted that we will need some Server Pools and groups before we can get started. We will have to ask the administrator to assign us access to those pools and groups. It's time now to login to our newly created account. Logging in to Oracle VM Manager Again we will need to either access the URL locally by typing http://127.0.0.1:8888/OVS or by typing the following: http://hostname:8888/ OVS. If we are accessing the Oracle VM Manager Portal remotely, replace the "hostname" with either the FQDN (Fully Qualified Distinguished Name) if the machine is registered in our DNS or just the hostname of the VM Manager machine. We can login to the portal by simply typing in our Username and Password that we just created. Depending on the role and the server pools that we have been assigned, we will be displayed with the tabs upon the screen as shown in the following table. To change the role, we will need to contact our enterprise domain administrator. Only administrators are allowed to change the roles of accounts. If we forget our password, we can click on Forgot Password and on submitting our account name, the password will be sent to the registered email address that we had provided when we registered the account. The following table discusses the assigned tabs that are displayed for each Oracle VM Manager roles:   Role Grants User Virtual Machines, Resources Administrator Virtual Machines, Resources, Servers, Server Pools, Administration Manager Virtual Machines, Resources, Servers, Server Pools   We can obviously change the roles by editing the Profile (on the upper-right section of the portal). As it can be seen in the following screenshot, we have access to the Virtual Machines pane and the Resources pane. We will continue to add Servers to the pool when logged in as admin. Oracle VM management: Managing Server Pool A Server Pool is logically an autonomous region that contains one or more physical servers and the dynamic nature of such pool and pools of pools makes what we call  an infinite Cloud infrastructure. Currently Oracle has its Cloud portal with Amazon but it is very much viable to have an IntraCloud portal or private Cloud where we can run all sorts of Linux and Windows flavors on our Cloud backbone. It eventually rests on the array of SAN, NAS, or other next generation storage substrate on which the VMs reside. We must ensure that we have the following prerequisites properly checked before creating the Virtual Machines on our IntraCloud Oracle VM. Oracle VM Servers: These are available to deploy as Utility Master, Server Master pool, and Virtual Machine Servers. Repositories: Used for Live Migration or Hot Migration of the VMs and for local storage on the Oracle VM Servers. FQDN/IP address of Oracle VM Servers: It is better to have the Oracle VM Servers known as OracleVM01.AVASTU.COM and OracleVM02.AVASTU. COM. This way you don't have to bother about the IP changes or infrastructural relocation of the IntraCloud to another location. Oracle VM Agent passwords: Needed to access the Oracle VM Servers. Let's now go about exploring the designing process of the Oracle VM. Then we will do the following systematically: Creating the Server Pool Editing Server Pool information Search and retrieval within Server Pool Restoring Server Pool Enabling HA Deleting a Server Pool However, we can carry out these actions only as a Manager or an Administrator. But first let's take a look at the decisions on what type of Server Pools will suit us the best and what the architectural considerations could be around building your Oracle VM farm.
Read more
  • 0
  • 0
  • 9730

article-image-aspnet-35-cms-adding-security-and-membership-part-2
Packt
16 Oct 2009
8 min read
Save for later

ASP.NET 3.5 CMS: Adding Security and Membership (Part 2)

Packt
16 Oct 2009
8 min read
Now that you understand the process behind forms authentication, we need to add it to our application. The process will be slightly different because we already have a database to use, but without the ASP.NET membership schema. We'll add that to the database and then create some user accounts and membership roles to handle the security for our application. We'll also secure some of our content and add a menu to our Master Page to navigate between the pages of our Content Management System. Preparing an existing SQL database As we have an existing database, we can't create a new database for our membership and authentication system. Well, actually we could, but using a second database is problematic when we upload the application to a host because many web hosting companies allow only a single database under the hosting plan. Besides, we can easily add the membership schema the same way we did earlier in the article with our empty database, using aspnet_regsql.exe. Previously we used the wizard, this time we'll use the command line. If you take a look at the database in SQL Server Management Studio Express now, before we execute the command to add the schemas, you should see the few tables that were already created, as shown below: The aspnet_regsql.exe tool Using the command line, the executable is simple, as long as you know the command line arguments. The syntax and command arguments for aspnet_regsql.exe are available online at http://msdn.microsoft.com/en-us/library/x28wfk74.aspx. The following table shows the arguments we will use: Argument Description What we use -S The server name SQLEXPRESS -U The database username sa -P The database password SimpleCMS -d The database name SimpleCMS_Database -A The schema functions to install All functions   Our command line will look like this (all one line): aspnet_regsql.exe -S .SQLEXPRESS -U sa -P SimpleCMS -d SimpleCMS_Database -A all To run the command line, go to Start | Run and enter cmd in the Run dialog box. Press Enter and you will be at a command prompt. Type cd C:WINDOWSMicrosoft.NETFrameworkv2.0.50727 and press Enter again, and you will be in the correct folder to find aspnet_regsql.exe. Note that you may need to change the path if your ASP.NET framework files are in a different location. Type the command line above and press Enter, and you should see that the command completed successfully, with a dialog similar to that below: Now that we have executed the aspnet_regsql.exe command line, if you look at the database tables in SQL Server Management Studio Express, you should see the added table for the users, membership, and roles we will use in our application. User accounts Earlier in the article, we created a single user account for accessing protected content. In a real-world environment, we would normally have many user accounts, way too many to add each account to each page we wanted to protect. Fortunately, the ASP.NET framework provides us with membership roles that we can place user accounts in, allowing us to define our access by role, not by user account. But first, we need some user accounts. Let's start by creating three accounts in our application  - User1, User2, and Administrator. Open the SimpleCMS web site in Visual Web Developer 2008 Express. Use the downloadable code provided for Chapter 4 of this book, it has the web.config file modified similar to what we did when we walked through the forms authentication demo earlier in the chapter. Open the Web Site Administration Tool by clicking on Website and then ASP.NET Configuration. If you click on the Security tab, you will see that we have no users configured for this application.  As you did earlier in the article, click on Create User and create the three users with user names of User1, User2, and Administrator. Use Password! as the password for each, and provide a valid email address for each (they can have the same email for testing). Also, provide a question and answer such as Favorite Color? and Blue. You can use the same question and answer for all three accounts if you wish. Each user entry should look something like the following: If you return to the Security tab, you will notice that we have three user accounts, but no roles for those accounts. Let's add them next. Membership roles ASP.NET membership roles provide the ability to group many individual accounts into a single role to provide access to a resource such as a page or application. Changing access for an individual user then becomes a simple task of assigning them to or removing them from the appropriate role. A single user account can belong to multiple roles to provide extremely granular access to the application resources if your security demands are extensive. To add roles to our application, we first need to enable roles. On the Security tab of the Web Site Administration Tool, under Roles, you should see a link to enable roles. Enabling roles consists of simply adding the following line to the web.config file in the system.web section: <roleManager enabled="true" /> Similar to the membership provider we created earlier, roles require a role provider. We need to add this provider to the role manager, so edit the web.config roleManager section to read: <roleManager enabled="true"><providers><clear/><add name="AspNetSqlRoleProvider"connectionStringName="SimpleCMS_DatabaseConnectionString"applicationName="/"type="System.Web.Security.SqlRoleProvider, System.Web,Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /></providers></roleManager> This adds an AspNetSqlRoleProvider that uses our connection string to the SimpleCMS database. At this point we have no roles defined, so let's create a few. Open the Web Site Administration Tool. If it's already open, you may need to close and reopen it because we modified the web.config file to add the role provider. Now, open the Security tab. In the Roles section, click on Create or manage roles. Let's create an administration role first. We'll need it to secure areas to just administrative access. Simply enter Administrator, click on Add Role, and you'll see the new role in the list. Add roles for Author, Editor, and Registered User in the same manner. The roles list should look something like the following figure when you finish: Adding users to roles Once we have users and roles created, we need to assign users to roles. To do this, use the Security tab of the Web Site Administration Tool, under the Users section, to manage users.  You'll see a list of user accounts, in our case all three of them, along with the ability to edit the user, delete the user, and edit the user's roles. Click on Edit roles next to the Administrator user and you'll see a checkbox list of user roles this account can be added to. Any roles currently assigned to the user will be checked. As there are currently none, check the Administrator role, and the Administrator user will be immediately added to the Administrator role, as shown below: If you were to look at the database tables that hold the user accounts and roles, you would see something like this for the users: Similarly, the roles would look like this: You'll note that both the users and the roles contain an ApplicationID that defines what application these users and roles belong to, and that each user or role is identified by a UserID or RoleID. These are automatically created by the ASP.NET membership framework and are globally unique identifiers (GUIDs), which ensure that the specific user or role is unique across all possible applications and uses of this specific database store. You would also find in the database a table that identifies users in roles, looking something like this: You'll notice that this is a joining table, used in a database when there is a many-to-many relationship. Many users can belong to a role and a user can belong to many roles, thus the use of this table. You'll also notice that the database table uses the UserID and RoleID, making it very hard to simply look at this table directly to find what users are assigned to what roles.  Fortunately, with the ASP.NET framework, you're isolated from having to work directly with the database, as well as relieved from having to create it and the code needed to access it.
Read more
  • 0
  • 0
  • 2539

article-image-managing-content-through-tagging-grails-part-1
Packt
16 Oct 2009
9 min read
Save for later

Managing Content through Tagging in Grails: Part 1

Packt
16 Oct 2009
9 min read
Add basic tagging Tagging is a loose, community-based way of categorizing content. It allows a group of people to categorize by consensus. Anyone is able to tag a piece of content. The more a tag is used, the more meaning it takes on and the more widely used it becomes. This categorization by consensus has been dubbed as folksonomy (http://en.wikipedia.org/wiki/Folksonomy) So let's get started by building our tagging support. Tagging domain model When implementing tagging in our system, we need to consider the following: We must be able to have many tags in our system We must be able to associate a single tag with many different files and messages We need to make sure that new domain objects can be easily tagged without having to change the tagging logic We want to know when a domain object was tagged To satisfy these requirements, we need to create the following new domain classes: Tag—to store the name of the tag. There is one instance of this class per unique tag name in the application. Tagger—to store the relationship from domain objects to a tag. This allows us to store the date a tag was added to a domain object. Let's create these domain classes and then write a test to prove that we can tag a message using this tagging structure. The Tag class We are going to separate the tagging classes out from our application domain classes. Create a folder under grails-app/domain called tagging. This is where we will put the domain model to implement tagging. Our Tag class is extremely simple and holds only a name property: package taggingclass Tag { String name static constrains = { name( blank: false ) } } The Tagger class The next class that we are going to create is the Tagger class. In relational terms, this object represents a link table between a Tag and any other domain class. It is important that the relationship between tagged domain classes and the Tagger relationship class is unidirectional. By this, we mean the domain classes are allowed to know that they can be tagged, but tags do not know which domain classes can be tagged, otherwise every tagged domain class would need a special relationship class. Create the Tagger class as a domain class in the tagging package as follows: package taggingclass Tagger { Tag tag static constraints = { tag( nullable: false ) }} The basics of our tagging model are complete! We now need some logic to allow tags to be created. Create a new service class called TagService under grails-app/services/tagging, as shown below: package taggingclass TagService { boolean transactional = true def createTagRelationships(String spaceDelimitedTags) { return spaceDelimitedTags?.split(' ')?.collect { tagName -> createTagRelationship( tagName ) }}def createTagRelationship(String tagName) {def tag = Tag.findByName(tagName)?: new Tag(name: tagName).save()return new Tagger( tag: tag )} This service provides two utility methods to create new relationships by tag name or by a space delimited string of tag names. The important behavior of these two methods is that they do not allow duplicate tags to be created in the application. If a tag name already exists, the tag will be retrieved from the database and used as the tag in the relationship. Notice that the createTagRelationships method is using the collect method to simplify what would normally take a few more lines of code to achieve. The collect method is dynamically added to any object that can be iterated over. For example, collections, arrays, strings and so on. It takes a closure as its argument and executes this closure for each item in the collection. The return value from each execution of the closure is added to a new collection that the collect method builds up and then returns once it has finished iterating the original collection. In createTagRelationship, we are using another neat language feature of Groovy called the "Elvis operator". It is named so, as it looks like Elvis' hair style. This is a shorter version of the normal Java ternary operator. If the operand being checked is true then the checked operand will be returned as the default, otherwise the alternative operand will be used. So in our example:     def tag = Tag.findByName(tagName) ?: new Tag(name: tagName).save() If a tag can be found from the database then it is used, otherwise a new tag is created. Tagging a message The next step is to allow a message to be tagged. Write some integration tests to make sure the relationships are working before using tagging in the application. In the folder test/integration/app, create the file TaggableIntegrationTests.groovy and add the following code: package appimport tagging.Tagclass TaggableIntegrationTest extends GroovyTestCase { User flancelot protected void setUp() { flancelot = User.findByUsername('flancelot') Tag.list().each { it.delete() } Message.list().each { it.delete() } }} The code above sets up the test data needed to create messages and associate tags to messages. Remember that the flancelot user already exists because it was created by the BootStrap class. The first test will determine that we can add tags to a message and then retrieve messages by tag. Add the following test method to your test class: void testCanRetrieveMessagesByTags() { Message message = new Message(user: flancelot, title: 'tagged', detail: "I've been tagged.").save(flush: true) Message secondMessage = new Message(user: flancelot, title: 'other tagged', detail: "I've been tagged.").save(flush: true) message.addTag('urgent') message.addTag('late') secondMessage.addTag('urgent') def taggedMessages = Message.withTag( 'urgent' ) assertEquals(2, taggedMessages.size()) assertEquals(2, Tag.list().size()) def secondMessages = Message.withTag( 'late' ) assertEquals(1, secondMessages.size()) assertEquals(2, Tag.list().size())} The test above does the following: Creates two new messages Adds the urgent tag to both messages Adds the late tag to one message Checks if we can retrieve both messages by using the urgent tag Checks if only one message is returned for the late tag Notice that the highlighted lines of code have not been implemented yet. To allow this test to pass, we need to add the following methods to the Message domain class: addTag—instance method to allow a message to be tagged withTag—class method to retrieve all messages with a particular tag Add the following method to the Message class (don't forget to import tagging.Tagger): def addTag(String tagName) { tags = (tags)?:[] tags << tagService.createTagRelationship( tagName )} This method simply delegates the creation of the tag relationship off to the TagService class, and then stores the relationship in the tags list. Add the following method to the Message class that retrieves all messages with a given tag name: def static withTag(String tagName) { return Message.withCriteria { tags { tag { eq('name', tagName ) } } }} This method must be static on the Message class, as it is used to load message instances for a given tag. We do not want to have to instantiate a message before we can perform the search. Before running the test, you will notice both of these new methods assume that there is a property on the Message class called tags. This has not yet been created. We need to create a one-to-many relationship from Message to Tagger that will allow messages to be tagged. We also need to inject the TagService into new instances of the Message class so the work for creating a new tag relationship can be delegated. Add the relationship to the Message class and inject TagService as shown below: class Message { def tagService static hasMany = [tags:Tagger] ...} Now we can run our tests by entering the following on the command line: grails test-app We should see some output in the command line similar to: Running test app.TaggableTest... testCanRetrieveMessagesByTags...SUCCESS Tagging a file Now that we have implemented tagging for messages, we need to make tagging available for files. Currently the logic for creating and fetching tags is in the Message domain class. We need to extract this logic so the File domain class can reuse it. It's time to look at how GORM supports inheritance. GORM inheritance The GORM supports inheritance of domain classes by default through the underlying Hibernate framework. Hibernate has a number of strategies for handling inheritance and Grails supports the following two: Table-per-hierarchy—this strategy creates one database table per inheritance hierarchy. This is the default strategy in Grails. Table-per-subclass—this strategy creates a database table for each subclass in an inheritance hierarchy and treats the inheritance (is a) relationship as a foreign key (has a) relationship. Taking our domain as an example, we have two classes. They are Message and File. We are going to make them both extend a super class Taggable, which will handle all of our tagging logic and state. Table-per-hierarchy If we were to choose the table-per-hierarchy strategy, we would end up with one table called Taggable that contained the data for both Message and File. The database structure would look something like: The interesting side-effect of this approach is that all of the fields to be persisted must be nullable. If a File is created and persisted, it is obviously not possible for the fields from Message to be populated. Table-per-subclass By using the table-per-subclass strategy, we would keep two separate tables called Message and File, and both would have the tags relationship inherited from Taggable. So the Message table will look like: We can see in the diagram above that the Message and File tables have remained separate and a table representing the superclass Taggable has been created, which the subclass tables have foreign key relationships to. In the table-per-subclass strategy, a table must exist to represent the inheritance (is a) relationship. We are going to follow the table-per-subclass strategy so that we can retain database level data integrity. The default behavior for GORM is to use the table-per-hierarchy strategy. To override this we must use the mapping property: static mapping = { tablePerHierarchy false}
Read more
  • 0
  • 0
  • 2050

article-image-feeds-facebook-applications
Packt
16 Oct 2009
7 min read
Save for later

Feeds in Facebook Applications

Packt
16 Oct 2009
7 min read
{literal} What Are Feeds? Feeds are the way to publish news in Facebook. As we have already mentioned before, there are two types of feeds in Facebook, News feed and Mini feed. News feed instantly tracks activities of a user's online friends, ranging from changes in relationship status to added photos to wall comments. Mini feed appears on individuals' profiles and highlights recent social activity. You can see your news feed right after you log in, and point your browser to http://www.facebook.com/home.php. It looks like the following, which is, in fact, my news feed. Mini feeds are seen in your profile page, displaying your recent activities and look like the following one: Only the last 10 entries are being displayed in the mini feed section of the profile page. But you can always see the complete list of mini feeds by going to http://www.facebook.com/minifeed.php. Also the mini feed of any user can be accessed from http://www.facebook.com/minifeed.php?id=userid. There is another close relation between news feed and mini feed. When applications publish a mini feed in your profile, it will also appear in your friend's news feed page. How to publish Feeds Facebook provides three APIs to publish mini feeds and news feeds. But these are restricted to call not more than 10 times for a particular user in a 48 hour cycle. This means you can publish a maximum of 10 feeds in a specific user's profile within 48 hours. The following three APIs help to publish feeds: feed_publishStoryToUser—this function publishes the story to the news feed of any user (limited to call once every 12 hours). feed_publishActionOfUser—this one publishes the story to a user's mini feed, and to his or her friend's news feed (limited to call 10 times in a rolling 48 hour slot). feed_publishTemplatizedAction—this one also publishes mini feeds and news feeds, but in an easier way (limited to call 10 times in a rolling 48 hour slot). You can test this API also from http://developers.facebook.com/tools.php?api, and by choosing Feed Preview Console, which will give you the following interface: And once you execute the sample, like the previous one, it will preview the sample of your feed. Sample application to play with Feeds Let's publish some news to our profile, and test how the functions actually work. In this section, we will develop a small application (RateBuddies) by which we will be able to send messages to our friends, and then publish our activities as a mini feed. The purpose of this application is to display friends list and rate them in different categories (Awesome, All Square, Loser, etc.). Here is the code of our application: index.php<?include_once("prepend.php"); //the Lib and key container?><div style="padding:20px;"><?if (!empty($_POST['friend_sel'])){ $friend = $_POST['friend_sel']; $rating = $_POST['rate']; $title = "<fb:name uid='{$fbuser}' useyou='false' /> just <a href='http://apps.facebook.com/ratebuddies/'>Rated</a> <fb:name uid='{$friend}' useyou='false' /> as a '{$rating}' "; $body = "Why not you also <a href='http://apps.facebook.com/ratebuddies/'>rate your friends</a>?";try{//now publish the story to user's mini feed and on his friend's news feed $facebook->api_client->feed_publishActionOfUser($title, $body, null, $null,null, null, null, null, null, null, 1); } catch(Exception $e) { //echo "Error when publishing feeds: "; echo $e->getMessage(); }}?> <h1>Welcome to RateBuddies, your gateway to rate your friends</h1> <div style="padding-top:10px;"> <form method="POST"> Seect a friend: <br/><br/> <fb:friend-selector uid="<?=$fbuser;?>" name="friendid" idname="friend_sel" /> <br/><br/><br/> And your friend is: <br/> <table> <tr> <td valign="middle"><input name="rate" type="radio" value="funny" /></td> <td valign="middle">Funny</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="hot tempered" /></td> <td valign="middle">Hot Tempered</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="awesome" /></td> <td valign="middle">Awesome</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="naughty professor" /></td> <td valign="middle">Naughty Professor</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="looser" /></td> <td valign="middle">Looser</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="empty veseel" /></td> <td valign="middle">Empty Vessel</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="foxy" /></td> <td valign="middle">Foxy</td> </tr> <tr> <td valign="middle"><input name="rate" type="radio" value="childish" /></td> <td valign="middle">Childish</td> </tr> </table> &nbsp; <input type="submit" value="Rate Buddy"/> </form> </div></div> index.php includes another file called prepend.php. In that file, we initialized the facebook api client using the API key and Secret key of the current application. It is a good practice to keep them in separate file because we need to use them throughout our application, in as many pages as we have. Here is the code of that file: prepend.php<?php// this defines some of your basic setupinclude 'client/facebook.php'; // the facebook API library// Get these from ?http://www.facebook.com/developers/apps.phphttp://www.facebook.com/developers/apps.php$api_key = 'your api key';//the api ket of this application$secret = 'your secret key'; //the secret key$facebook = new Facebook($api_key, $secret); //catch the exception that gets thrown if the cookie has an invalid session_key in it try { if (!$facebook->api_client->users_isAppAdded()) { $facebook->redirect($facebook->get_add_url()); } } catch (Exception $ex) { //this will clear cookies for your application and redirect them to a login prompt $facebook->set_user(null, null); $facebook->redirect($appcallbackurl); }?> The client is a standard Facebook REST API client, which is available directly from Facebook. If you are not sure about these API keys, then point your browser to http://www.facebook.com/developers/apps.php and collect the API key and secret key from there. Here is a screenshot of that page: Just collect your API key and Secret Key from this page, when you develop your own application. Now, when you point your browser to http://apps.facebooks.com/ratebuddies and successfully add that application, it will look like this: To see how this app works, type a friend in the box, Select a friend, and click on any rating such as Funny or Foxy. Then click on the Rate Buddy button. As soon as the page submits, open your profile page and you will see that it has published a mini feed in your profile.
Read more
  • 0
  • 0
  • 5373
Packt
16 Oct 2009
6 min read
Save for later

Network Configuration—IPv6 with FreeBSD

Packt
16 Oct 2009
6 min read
Several methods were introduced to reduce the usage of IP addresses in the internet including: Classless Interdomain Routing (CIDR): This introduced the death of classful addressing (for example Class A, B, C) by a new subnetting method which is not limited, unlike the classful method. Network Address Translation (NAT): Using NAT you do not need to use public IP addresses on your internal hosts. Using CIDR subnets and NAT only helped IPv4 to live a few years longer, but was not the ultimate cure to the problem. Besides the addressing issues, there were other problems with IPv4 which could not be easily solved. These issues include the following: The size of internet routing tables was growing rapidly and this forced backbone providers to upgrade their networking gears. The IPv4 was very inefficient for high throughput links and did not support QoS by nature. Back in the early 90s, IETF had started a workgroup to solve the deficiencies of the IP protocol. In 1995, the IETF published the initial drafts of IPv6 as the next generation IP. Since then, the protocol has matured enormously and been implemented in many operating systems. IPv6 Facts If you are not familiar with IPv6, here is a very quick look at the difference between IPv4 and IPv6. (For a more detailed insight into IPv6 and its configuration in various operating systems, it is recommended that you read Running IPv6 book by Iljitsch van Beijnum). Fact One—Addressing Addressing in IPv6 is quite different from legacy IPv4 addresses. IPv6 uses 128-bit address space unlike the 32-bit addressing system in IPv4. A typical IPv6 address would look like—2002:a00:1:5353:20a:95ff:fef5:246e Fact Two—Address Types There are 4 types of addresses in IPv6: Unicast: A typical IPv6 address you use on a host. Multicast: Addresses that start with ff:: are equivalent to IPv4 multicast. Anycast: A typical IPv6 address that is used on a router. Reserved: Includes loopback, link-local, site-local, and so on. Fact Three—ARP There is no ARP! MAC to IP mapping is no longer needed as MAC addresses are embedded into IPv6 addresses. Instead, ND is born. ND is used to auto-configure addresses on hosts, duplicated detection, and so on. Fact Four—Interface Configuration If you are new to IPv6, you will be shocked to see an IPv6 address, telling yourself that you are in trouble assigning addresses to interfaces or remembering the addresses. However, it is not all that hard. In most cases, you can have your host autoconfigure IPv6 address on its interfaces. Typically, you should set this up only on your network gateway (router) manually. Using IPv6 Running FreeBSD 7, the kernel is already IPv6 enabled. However, you should manually enable IPv6 in the UserLand, by adding the following line to the /etc/rc.conf configuration file: ipv6_enable="YES" And manually start the appropriate rc script (or reboot the system) for the changes to take effect: # /etc/rc.d/network_ipv6 start This will enable IPv6 on all interfaces that are IPv6 capable. This behavior is changed by modifying the following variable in the /etc/rc.conf file: ipv6_network_interfaces="fxp0 bge0" This will enable IPv6 support on specified interfaces. The default value for this variable is auto. Once you enable IPv6, interfaces will discover the IPv6 enabled routers on the network and build their own IPv6 addresses based on the network prefix they receive from the router. Configuring Interfaces In a typical scenario, IPv6 network stack will automatically look for an IPv6 enabled router on the same network for each interface and try to automatically configure the IPv6 address on the interface. The following is an example of an automatically configured interface(replace the $ with %): # ifconfig ed0 ed0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 ether 00:1c:42:8d:5d:bf inet6 fe80::21c:42ff:fe8d:5dbf$ed0 prefixlen 64 scopeid 0x1 inet 192.168.0.225 netmask 0xffffff00 broadcast 192.168.0.255 inet6 2a01:3c8::21c:42ff:fe8d:5dbf prefixlen 64 autoconf media: Ethernet autoselect (10baseT/UTP) Beside the IPv4 address, there are two IPv6 addresses on the interface. One address begins with fe80:: and identified with the scopeid 0x1 tag, which is called a link-local address. Another address begins with 2a01:3c8::, which is the unicast address of this interface. The unicast address prefix is obtained from the IPv6 router on the network. The whole address is created using the 64 bits Extended Unique Identifier (EUI-64) algorithm, which consists of the hosts MAC address with some minor modifications. The link-local address (that is from the reserved address pool) always starts with fe80:: and is used for local network usage. This can be compared with RFC1819 private addresses that are suitable for local use. The network stack will automatically assign a link-local address to each IPv6 enabled interface, regardless whether an IPv6 router is discovered on the network. This means that in a scenario of a home network or a lab network, you do not need to run an IPv6 router or have a valid IPv6 prefix in order to establish an IPv6 network. All the hosts will be automatically provisioned with a link-local address, so they can exchange IPv6 traffic. The network discovery protocol (NDP) helps the host find the router on the network and then create a unicast address for the interface. NDP is known as the equivalent to ARP protocol in IPv6. The ndp(8) utility is used to control the behavior of this protocol: # ndp -a Neighbor Linklayer Address Netif Expire S Flags 2a01:3c8:: 0:16:cb:98:d4:bf ed0 20s R R 2a01:3c8::21c:42ff:fe8d:5dbf 0:1c:42:8d:5d:bf ed0 permanent R fe80::216:cbff:fe98:d4bf$ed0 0:16:cb:98:d4:bf ed0 23h58m48s S R fe80::21c:42ff:fe8d:5dbf$ed0 0:1c:42:8d:5d:bf ed0 permanent R fe80::1%lo0 (incomplete) lo0 permanent R The above example shows the discovered IPv6 hosts(replace the $ with %). The ed0 interface is connected to an IPv6 enabled network and receives a valid prefix via a router (the first entry of the list). The second entry is the unicast address of the ed0. The third and the fourth entries are link-local address for the router and our host. And the last entry belongs to the local host. As you have seen so far, there are some special (reserved) IPv6 addresses. The following table shows a list of reserved addresses:   Address Name Description :: Unspecified Equivalent to 0.0.0.0 in Pv4 ::1 Loopback address Equivalent to 127.0.0.1 in IPv4 fe80:: Link-local fec0:: Site-local ff00:: Multicast   In case you want to configure the static IPv6 address on an interface, it can be done as in a typical IPv4 scenario: # ifconfig vr0 inet6 2a01:3c8::21c:42ff:dead:beef prefixlen 64 This will manually configure an IP address on the specified interface. Note the prefixlen keyword that is equivalent to subnet mask in IPv4.
Read more
  • 0
  • 0
  • 4973

article-image-exceptions-and-logging-apache-struts-2
Packt
16 Oct 2009
8 min read
Save for later

Exceptions and Logging in Apache Struts 2

Packt
16 Oct 2009
8 min read
Handling exceptions in Struts 2 Struts 2 provides a declarative exception handling mechanism that can be configured globally (for an entire package), or for a specific action. This capability can reduce the amount of exception handling code necessary inside actions under some circumstances, most notably when underlying systems, such as our services, throw runtime exceptions (exceptions that we don't need to wrap in a try/catch or declare that a method throws). To sum it up, we can map exception classes to Struts 2 results. The exception handling mechanism depends on the exception interceptor. If we modify our interceptor stack, we must keep that in mind. In general, removing the exception interceptor isn't preferred. Global exception mappings Setting up a global exception handler result is as easy as adding a global exception mapping element to a Struts 2 configuration file package definition and configuring its result. For example, to catch generic runtime exceptions, we could add the following: <global-exception-mappings><exception-mapping result="runtime"exception="java.lang.RuntimeException"/></global-exception-mappings> This means that if a java.lang.RuntimeException (or a subclass) is thrown, the framework will take us to the runtime result. The runtime result may be declared in an element, an action configuration, or both. The most specific result will be used. This implies that an action's result configuration might take precedence over a global exception mapping. For example, consider the global exception mapping shown in the previous code snippet. If we configure an action as follows, and a RuntimeException is thrown, we'll see the locally defined runtime result, even if there is a global runtime result. <action name="except1"class="com.packt.s2wad.ch09.examples.exceptions.Except1"><result name="runtime">/WEB-INF/jsps/ch9/exceptions/except1-runtime.jsp</result>... This can occasionally lead to confusion if a result name happens to collide with a result used for an exception. However, this can happen with global results anyway (a case where a naming convention for global results can be handy). Action-specific exception mappings In addition to overriding the result used for an exception mapping, we can also override a global exception mapping on a per-action basis. For example, if an action needs to use a result named runtime2 as the destination of a RuntimeException, we can configure an exception mapping specific to that action. <action name="except2"class="com.packt.s2wad.ch09.examples.exceptions.Except1"><exception-mapping result="runtime2"exception="java.lang.RuntimeException"/>... As with our earlier examples, the runtime2 result may be configured either as a global result or as an action-specific result. Accessing the exception We have many options regarding how to handle exceptions. We can show the user a generic "Something horrible has happened!" page, we can take the user back and allow them to retry the operation or refill the input form, and so on. The appropriate course of action depends on the application and, most likely, on the type of exception. We can display exception-specific information as well. The exception interceptor pushes an exception encapsulation object onto the stack with the exception and exceptionStack properties. While the stack trace is probably not appropriate for user-level error pages, the exception can be used to help create a useful error message, provide I18N property keys for messages (or values used in messages), suggest possible remedies, and so on. The simplest example of accessing the exception property from our JSP is to simply display the exception message. For example, if we threw a RuntimeException, we might create it as follows: throw newRuntimeException("Runtime thrown from ThrowingAction"); Our exception result page, then, could access the message using the usual property tag (or JSTL, if we're taking advantage of Struts 2's custom request processor): <s:property value="exception.message"/> The underlying action is still available on the stack—it's the next object on the value stack. It can be accessed from the JSP as usual, as long as we're not trying to access properties named exception or exceptionStack, which would be masked by the exception holder. (We can still access an action property named exception using OGNL's immediate stack index notation—[1].exception.) Architecting exceptions and exception handling We have pretty good control over what is displayed for our application exceptions. It is customizable based on exception type, and may be overridden on a per-action basis. However, to make use of this flexibility, we require a well-thought-out exception policy in our application. There are some general principles we can follow to help make this easier. Checked versus unchecked exceptions Before we start, let's recall that Java offers two main types of exceptions—checked and unchecked. Checked exceptions are exceptions we declare with a throws keyword or wrapped in a try/catch block. Unchecked exceptions are runtime exceptions or a subclass. It isn't always clear what type we should use when writing our code or creating our exceptions. It's been the subject of much debate over the years, but some guidelines have become apparent. One clear thing about checked exceptions is that they aren't always worth the aggravation they cause, but may be useful when the programmer has a reasonable chance of recovering from the exception. One issue with checked exceptions is that unless they're caught and wrapped in a more abstract exception (coming up next), we're actually circumventing some of the benefits of encapsulation. One of the benefits being circumvented is that when exceptions are declared as being thrown all the way up a call hierarchy, all of the classes involved are forced to know something about the class throwing the exception. It's relatively rare that this exposure is justifiable. Application-specific exceptions One of the more useful exception techniques is to create application-specific exception classes. A compelling feature of providing our own exception classes is that we can include useful diagnostic information in the exception class itself. These classes are like any other Java class. They can contain methods, properties, and constructors. For example, let's assume a service that throws an exception when the user calling the service doesn't have access rights to the service. One way to create and throw this exception would be as follows: throw new RuntimeException("User " + user.getId()+ " does not have access to the 'update' service."); However, there are some issues with this approach. It's awkward from the Struts 2's standpoint. Because it's a RuntimeException, we have only one option for handling the exception—mapping a RuntimeException to a result. Yes, we could map the exception type per-action, but that gets unwieldy. It also doesn't help if we need to map two different types of RuntimeExceptions to two different results. Another potential issue would arise if we had a process that examined exceptions and did something useful with them. For example, we might send an email with user details based on the above exception. This would amount to parsing the exception message, pulling out the user ID, and using it to get user details for inclusion in the email. This is where we'd need to create an exception class of our own, subclassed from RuntimeException. The class would have encapsulated exception related information, and a mechanism to differentiate between the different types of exceptions. A third benefit comes when we wrap lower-level exceptions—for example, a Spring-related exception. Rather than create a Spring dependency up the entire call chain, we'd wrap it in our own exception, abstracting the lower-level exception. This allows us to change the underlying implementation and aggregate differing exception types under one (or more) application-specific exception. One way of creating the above scenario would be to create an exception class that takes a User object and a message as its constructor arguments: package com.packt.s2wad.ch09.exceptions;public class UserAccessException extends RuntimeException {private User user;private String msg;public UserAccessException(User user, String msg) {this.user = user;this.msg = msg;}public String getMessage() {return "User " + user.getId() + " " + msg;}} We can now create an exception mapping for a UserAccessException (as well as a generic RuntimeException if we need it). In addition, the exception carries along with it the information needed to create useful messages: throw new UserAccessException(user,"does not have access to the 'update' service."); "Self-documenting" of code could be made even safer, in the sense of ensuring that it's only used in the ways in which it is intended. We could add an enum to the class to encapsulate the reasons the exception can be thrown, including the text for each reason. We'll add the following inside  our UserAccessException: public enum Reason {NO_ROLE("does not have role"),NO_ACCESS("does not have access");private String message;private Reason(String message) {this.message = message;}public String getMessage() { return message; }}; We'll also modify the constructor and getMessage() method to use the new Reason enumeration. public UserAccessException(User user, Reason reason) {this.user = user;this.reason = reason;}public String getMessage() {return String.format("User %d %s.",user.getId(), reason.getMessage());} Now, when we throw the exception, we explicitly know that we're using the exception class correctly (at least type-wise). The string message for each of the exception reasons is encapsulated within the exception class itself. throw new UserAccessException(user,UserAccessException.Reason.NO_ACCESS); With Java 5's static imports, it might make even more sense to create static helper methods in the exception class, leading to the concise, but understandable code: throw userHasNoAccess(user);
Read more
  • 0
  • 1
  • 10849

article-image-voice-menus-and-ivr-asterisknow
Packt
16 Oct 2009
3 min read
Save for later

Voice Menus and IVR in AsteriskNOW

Packt
16 Oct 2009
3 min read
Four Rules of IVR IVR systems can be hell to use; the main reason for this is that people designing IVR systems tend to complicate their functionality beyond the normal usage scope of a human being. The following four rules will enable you to implement a usable, humanly accessible, and maintainable IVR. Rule 1—Keep it narrow: Your IVR should be kept as simple as possible. Make sure that each of your steps in the IVR environment is not longer than five options. Most IVR users aren't able to remember all the options of an IVR system, when presented with a multitude of IVR options. Rule 2—Keep it shallow: Your IVR system's depth is in direct relation to the complexity of the IVR application. If your application has more than four levels, you need to revise your IVR plan. Most people (including yours truly) become extremely aggravated when confronted with an IVR system that is asking for too much information. Rule 3—Enable escape routes: Always give your IVR user the ability to break out of the IVR flow and talk to a live person. Some people simply can't handle the usage of an IVR system. Rule 4—If it works, don't fix it!: For some reason, companies tend to change their IVR flows every other day to support a new business model. An IVR system that constantly changes is a nightmare for users, as they never get used to the options of the system. If you must perform an update, make sure that your update doesn't affect that system in such a way that the users need to re-learn the system. Voice Menus—AsteriskNOW's IVR Generator AsteriskNOW provides a highly simplistic IVR generator, rightfully named—Voice Menus. The main usage of an IVR in a PBX is the implementation of an "Auto Attendant". Some PBX systems refer to auto-attendant and IVR as two different things. In AsteriskNOW, they are one and the same. At this point, click the Voice Menus link, located on your left-hand main menu. The following should appear on your screen: This interface enables editing, creation, or deletion of voice menus. Each menu is built from a set of operational directives (Steps) and functional keys (Keypress Events). Each voice menu also receives a mandatory name (Name), a form of logical entity description, and an Extension number (optional). The extension number enables PBX extensions or external users to dial into the specific voice menu indicated by the extension number. Voice Menu Steps—The Voice Menu Flow Steps are performed one after the other, in the order they appear on the screen. There are seventeen possible steps, available through the AsteriskNOW GUI. Once a step had been selected, the GUI will change, indicating the requirement for additional fields to be filled. The seventeen available steps are as follows:
Read more
  • 0
  • 0
  • 4754
article-image-user-input-validation-tapestry-5
Packt
16 Oct 2009
9 min read
Save for later

User Input Validation in Tapestry 5

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

article-image-deployment-reports-birt
Packt
15 Oct 2009
4 min read
Save for later

Deployment of Reports with BIRT

Packt
15 Oct 2009
4 min read
Everything in this article uses utilities from the BIRT Runtime installation package, available from the BIRT homepage at http://www.eclipse.org/birt. BIRT Viewer The BIRT Viewer is a J2EE application that is designed to demonstrate how to implement the Report Engine API to execute reports in an online web application. For most basic uses—such as for small to medium size Intranet applications—this is an appropriate approach. The point to keep in mind about the BIRT Web Viewer is that it is an example application. It can be used as a baseline for more sophisticated web applications that will implement the BIRT Report Engine API. Installation of the BIRT Viewer is documented at a number of places. The Eclipse BIRT website has some great tutorials at: http://www.eclipse.org/birt/phoenix/deploy/viewerSetup.php http://wiki.eclipse.org/BIRT/FAQ/Deployment This is also documented on my website in a series of articles introducing people to BIRT: http://digiassn.blogspot.com/2005/10/birt-report-server-pt-2.html I won't go into the details about installing Apache Tomcat as this is covered in depth in other locations, but I will cover how to install the Viewer in a Tomcat environment. For the most part these instructions can be used in other J2EE containers, such as WebSphere. In some cases a WAR package is used instead. I prefer Tomcat because it is a widely used open-source J2EE environment. Under the BIRT Runtime package is a folder containing an example Web Viewer application. The Web Viewer is a useful application as you require basic report viewing capabilities, such as parameter passing, pagination, and export capabilities to formats such as Word, Excel, RTF, and CSV. For this example, I have Apache Tomcat 5.5 installed into a folder at C:apache-tomcat-5.5.25. To install the Web Viewer, I simply need to copy the WebViewerExample folder from the BIRT Runtime to the web application folder at C:apache-tomcat-5.5.25webapps. Accessing the BIRT Web Viewer is as simple as calling the WebViewerExample Context. When copying the WebViewerExample folder, you can rename this folder to anything you want. Obviously WebViewerExample is not a good name for an online web application. So in the following screenshot, I renamed the WebViewerExample folder to birtViewer, and am accessing the BIRT Web Viewer test report. Installing Reports into the Web Viewer Once the BIRT Viewer is set up, Deploying reports is as simple as copying the report design files, Libraries, or report documents into the application's Context, and calling it with the appropriate URL parameters. For example, we will install the reports from the Classic Cars – With Library folder into the BIRT Web Viewer at birtViewer. In order for these reports to work, all dependent Libraries need to be installed with the reports. In the case of the example application, we currently have the report folder set to the Root of the web application folder. Accessing Reports in the Web Viewer Accessing reports is as simple as passing the correct parameters to the Web Viewer. In the BIRT Web Viewer, there are seven servlets that you can call to run reports, which are as follows: frameset run preview download parameter document output Out of these, you will only need frameset and run as the other servlets are for Engine-related purposes, such as the preview for the Eclipse designer, the parameter Dialog, and the download of report documents. Out of the these two servlets, frameset is the one that is typically used for user interaction with reports, as it provides the pagination options, parameter Dialogs, table of contents viewing, and export and print Dialogs. The run servlet only provides report output. There are a few URL parameters for the BIRT Web Viewer, such as: __format : which is the output format, either HTML or PDF. __isnull: which sets a Report Parameter to null, parameter name as a value. __locale: which is the reports locale. __report: which is the report design file to run. __document: which is the report document file to open. Any remaining URL parameter will be treated as a Report Parameter. In the following image, I am running the Employee_Sales_Percentage.rptdesign file with the startDate and endDate parameters set.  
Read more
  • 0
  • 0
  • 6279
Modal Close icon
Modal Close icon