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-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-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-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-managing-and-enhancing-multi-author-blogs-wordpress-27part-1
Packt
16 Oct 2009
18 min read
Save for later

Managing and Enhancing Multi-Author Blogs with WordPress 2.7(Part 1)

Packt
16 Oct 2009
18 min read
Creating an author page template If you have different authors on your blog, then my suggestion to you would be to display the biographical and contact information of each author on his own dedicated page. Luckily, WordPress allow us to do just that. Getting ready In this recipe, we're going to create an author page template for the purpose of displaying author related information. Make sure that you have understood the creation and usage of a page template. How to do it Create a new file named authors.php on your WordPress theme directory. Insert the following code into your file named authors.php: <?php/*Template Name: Authors Page*/?><?php get_header(); ?><div id="content" class="narrowcolumn"><?phpif(isset($_GET['author_name'])) :$curauth = get_userdatabylogin($author_name);else :$curauth = get_userdata(intval($author));endif;?><h2>About <?php echo $curauth->nickname; ?></h2><div class="excerpt"><?php echo $curauth->nickname; ?> personal website:<a href="<?php echo $curauth->user_url; ?>"><?php echo $curauth->user_url; ?></a></div><?php echo $curauth->user_description; ?><h2>Latest posts by <?php echo $curauth->nickname; ?>:</h2>Chapter 6133<ul><?php if ( have_posts() ) : while ( have_posts() ) :the_post(); ?><li><a href="<?php the_permalink() ?>"><?php the_title();?></a> on <?php the_time('d M Y'); ?></li><?php endwhile; else: ?><p><?php _e('No posts by this author.'); ?></p><?php endif; ?></ul></div><!--/content--><?php get_sidebar(); ?><?php get_footer(); ?> Save the file and upload it to the wp-content/themes/yourtheme folder of your WordPress install. Log in to your WordPress dashboard, create a new page, and select the Authors Page as a page template. Give it the title of your choice, such as, About the Author and publish the page. Open the single.php file from your theme. Depending on the theme that you're using, you may need to add the following code in order to display the author's name and a link to the author's page: Posted by <?php the_author_posts_link(); ?> Once you have saved the modifications made in your single.php file, visit one of your blog posts and click on the author name. The author page is displayed showing the author name, description, and web site. How it works The first thing that we need to know is the name of the author whose information is to be displayed. To do so, we have to get the author_name parameter sent via the GET method. With this value, we can initialize a $curauth php object that will allow us to get some personal information about the author, such as his web site, email, biography, and so on, with the help of the classic php syntax, that is, $curauth->nickname;. Once the author data, that is to be displayed, has been retrieved, we shall add a WordPress loop in order to be able to view the recent posts by this author. The following screenshot shows a well-prepared author page: There's more... In the preceding example we retrieved the author name, description, and web site URL. However, as you may know, users can provide much more information (in Administration, Profile, Your Profile options) such as their email address, AIM and Yahoo! messenger nickname, and login information. A few more template tags can be used to retrieve another kind of information from the author data. These tags are listed under the There's more! section of Displaying author-related information on posts, which we will see later in this article. Displaying a custom login form in your blog's sidebar It doesn't matter whether you're running a multi-author blog, or a blog where readers can register. Having a login form embedded in your sidebar will make your blog look a lot more professional and user friendly. Here is what you can expect from this recipe. In the following screenshot, a login form has been added to the K2 theme sidebar. Getting ready To achieve this recipe, you'll have to edit the sidebar.php file from your theme. The following hack works with WordPress 2.0 to 2.8. How to do it Open the sidebar.php file for editing. Find the opening <ul> tag and paste the following code under it: <li><?php global $user_ID, $user_identity, $user_level ?><?php if ( $user_ID ) : ?><h2><?php echo $user_identity ?></h2><ul><li><a href="<?php bloginfo('url') ?>/wp-login.php?action=logout&amp;redirect_to=<?php echo urlencode($_SERVER['REQUEST_URI']) ?>">Logout</a></li></ul><?php elseif ( get_option('users_can_register') ) : ?>Managing and Enhancing Multi-Author Blogs136<h2>Identification</h2><ul><li><form action="<?php bloginfo('url')?>/wp-login.php" method="post"><p><label for="log"><input type="text" name="log"id="log" value="<?php echo wp_specialchars (stripslashes($user_login), 1) ?>" size="22" /> User</label><br /><label for="pwd"><input type="password"name="pwd" id="pwd" size="22" /> Password</label><br /><input type="submit" name="submit" value="Login"class="button" /><label for="rememberme"><input name="rememberme"id="rememberme" type="checkbox" checked="checked"value="forever" /> Remember me</label><br /></p><input type="hidden" name="redirect_to" value="<?php echo$_SERVER['REQUEST_URI']; ?>"/></form></li><li><a href="<?php bloginfo('url')?>/wp-register.php">Register</a></li><li><a href="<?php bloginfo('url') ?>/wp-login.php?action=lostpassword">Recover password</a></li></ul><?php endif ?></li> Save the file. Your users can now login directly from your blog's sidebar. How it works The working of this code is quite simple. First, you initialize the global variables to get the user ID, name, and level. Then, you check the value of the $user_ID variable. If the value is not null, which means that the current user is logged in, you then display a quick hello user text and a link to log out. If the user isn't logged in, you check whether registering is allowed on the blog. If the user is logged in, then you simply display an HTML form that allows the user to log in directly from the blog. A link has also been included for registration if the current user doesn't have an account yet. This code was inspired from a tutorial available at www.wpdesigner.com. Adding a control panel to your blog's sidebar Now that you have learned how to check whether a user is logged in or not, why not learn how to add a small control panel to your blog's sidebar that is only visible to the logged in users. In this recipe, you'll learn how to achieve this task. Getting ready The upcoming piece of code works in exactly the same way as the code from the previous recipe does. It is all about checking if the user is logged in and whether he or she has the right to do a certain kind of thing. The following screenshot shows a simple, but useful, control panel which is similar to the one we're about to create: How to do it Open sidebar.php for editing. Find the first opening <ul> HTML tag, and paste the following code under the <ul> tag: <li><?php global $user_ID, $user_identity, $user_level ?><?php if ( $user_ID ) : ?><h2>Control panel</h2><ul><li>Identified as <strong><?php echo $user_identity ?></strong>.<ul><li><a href="<?php bloginfo('url') ?>/wp-admin/">Dashboard</a></li><?php if ( $user_level >= 1 ) : ?><li><a href="<?php bloginfo('url') ?>/wp-admin/post-new.php">Write an article</a></li><?php endif; ?><li><a href="<?php bloginfo('url') ?>/wp-admin/profile.php">Profile and personal options</a></li><li><a href="<?php bloginfo('url') ?>/wp-login.php?action=logout&amp;redirect_to=<?php echourlencode($_SERVER['REQUEST_URI']) ?>">Logout</a></li><?phpif (is_single()) {?><li><a href="<?php bloginfo('wpurl');?>/wp-admin/edit.php?p=<?php the_ID(); ?>">Edit Post</a></li><?php } ?></ul></li></ul><?php endif; ?></li> Once you are done, save the file. The allowed users can now go to their dashboard, edit their profile, or write a new post directly from the blog. How it works As mentioned earlier, this code works in the same way as the code that was used to create a login form in the sidebar. After you've made sure that the $user_ID variable isn't null, you work towards displaying the options available to the user. It is possible to define what a user can perform according to his role (administrator, author, contributor, subscriber, and so on). We're going to have a look at this in the next recipe. There's more... Now that you have learned how to add a control panel to the blog's sidebar, let's go ahead and try out something new. Adding a login form and a control panel Now that you know how to add a login form and a mini control panel to your blog's sidebar, why not try mixing the two codes? If the user isn't logged in, we'll display the login form. Otherwise, the custom panel will be shown to the user. The code below works in the same way as the two that we studied previously. Add the following code to the sidebar.php file of your theme: <li><?php global $user_ID, $user_identity, $user_level ?><?php if ( $user_ID ) : ?><h2>Control panel</h2><ul><li>Identified as <strong><?php echo $user_identity ?></strong>.<ul><li><a href="<?php bloginfo('url') ?>/wp-admin/">Dashboard</a></li><?php if ( $user_level >= 1 ) : ?><li><a href="<?php bloginfo('url') ?>/wp-admin/post-new.php">Write an article</a></li><?php endif; ?><li><a href="<?php bloginfo('url') ?>/wp-admin/profile.php">Profile and personal options</a></li><li><a href="<?php bloginfo('url') ?>/wp-login.php?action=logout&amp;redirect_to=<?php echo urlencode($_SERVER['REQUEST_URI']) ?>">Logout</a></li><?phpif (is_single()) {?><li><a href="<?php bloginfo('wpurl');?>/wp-admin/edit.php?p=<?php the_ID(); ?>">Edit Post</a></li><?php } ?></ul></li></ul><?php elseif ( get_option('users_can_register') ) : ?><h2>Identification</h2><ul><li><form action="<?php bloginfo('url') ?>/wp-login.php"method="post"><p><label for="log"><input type="text" name="log" id="log" value="<?php echo wp_specialchars(stripslashes($user_login), 1)?>" size="22" /> User</label><br /><label for="pwd"><input type="password" name="pwd" id="pwd"size="22" /> Password</label><br /><input type="submit" name="submit" value="Login"class="button" /><label for="rememberme"><input name="rememberme" id="rememberme" type="checkbox" checked="checked"value="forever" /> Remember me</label><br /></p><input type="hidden" name="redirect_to" value="<?php echo$_SERVER['REQUEST_URI']; ?>"/></form></li><li><a href="<?php bloginfo('url') ?>/wp-register.php">Register</a></li><li><a href="<?php bloginfo('url') ?>/wp-login.php?action=lostpassword">Recover password</a></li></ul><?php endif; ?></li> The custom logging form for unregistered users will look similar to the following screenshot: And the control panel for logged in users will look similar to the following screenshot: Configuring author roles Now that you have learned about the different aspects of the user's roles and capabilities, there's probably something that you're finding a little frustrating. By default, you can't configure author roles to fit your blog's needs. For example, a contributor can't upload images. Moreover, by default, you can't change it. Luckily, there's a plugin called Role Manager which allows you to configure author roles in the way that you want. Getting ready The Role Manager plugin can be found at the following link: http://www.im-web-gefunden.de/wordpress-plugins/role-manager/ Download it, unzip it onto your hard drive, and install it as any other WordPress plugin. How to do it Once the Role Manager plugin is installed, log in to your WordPress dashboard and go to Users | Roles. A list of all of the available user roles will be displayed. For each role you can define what the user can do. For example, you can choose to let a contributor upload images. What is even better is that you're not limited to the 5 default user roles that are provided by WordPress. The Role Manager plugin allows you to create new roles, as well as the ability to rename, copy, or delete existing ones. How it works The job of the Role Manager plugin is pretty easy. It simply creates custom roles with the options that you have defined and save it on the WordPress database. There's more... Now that we have configured the author roles, let's learn how to control the author's actions. Controlling what authors can do Even if your blog is powered by multiples authors, it is still your blog. Therefore, you shouldn't allow every author to have the right to edit posts or delete comments. Since version 2.0, WordPress features user roles. User roles are defined as a group of actions that can be accomplished by a specific range of users. For example, the administrator can edit theme files, but the subscribers can't. User roles and their capabilities Here are the 5 predefined roles for WordPress users: Administrator: The administrator is the blog owner. He has unlimited access to all of the administration features such as writing posts, editing his own posts along with the posts from other authors, installing plugins, selecting a new theme, editing themes, and editing plugin files. Editor: The editor can write or publish posts, upload images, edit his own posts, and manage other's posts. Author: The author can write, publish, and edit his own his own posts. He's also allowed to upload images for use in his posts. Contributor: A contributor can write posts but can't publish them himself. Once he has written a post, the post is pending approval from the administrator. The contributor can't upload images either. This role is very good for guest authors on your own blog. Subscriber: A subscriber is a registered user of your blog, but can't write posts. For an exhaustive description of user roles and capabilities, you should read the related page in WordPress Codex: http://codex.wordpress.org/Roles_and_Capabilities. Controlling what users can see in your theme In the previous example, we built a sidebar control panel that allows the user to edit the current post. However, the code doesn't let you control which kind of author is allowed to edit the current post. For now, even if only the users with a sufficient role level will be capable of editing the post, every logged in user can see the related link. The solution to that problem is a built-in WordPress function, called current_user_can(). As an argument, this function takes a string describing the action or the required role level to perform a specific task. For example, the following code will provide a link to edit the current post to the administrators only: <?phpif (current_user_can('level_10')){ ?><a href="<?php bloginfo('wpurl');?>/wp-admin/edit.php?p=<?php the_ID(); ?>">Edit Post</a><?php } ?> The current_user_can() function accepts user_0 to user_10 as a parameter. Here is the conversion table between the role levels and the roles: Suscriber: level_0 Contributor: level_1 Author: level_2 to level_4 Editor: level_5 to level_7 Administrator: level_8 to level_10 The current_user_can() function can also be used with a specific action as a parameter. This is the recommended use, as the level parameter is becoming obsolete. The following example checks if the current user can edit a post he previously published. If yes, then a link to edit the post will be displayed. <?phpif (current_user_can('edit_published_posts')){ ?><a href="<?php bloginfo('wpurl');?>/wp-admin/edit.php?p=<?php the_ID(); ?>">Edit Post</a><?php } ?> Here are all of the arguments that are accepted by the current_user_can() function:      switch_themes      edit_themes      activate_plugins      edit_plugins      edit_users      edit_files      manage_options      moderate_comments      manage_categories      manage_links      upload_files      import      unfiltered_html      edit_posts      edit_others_posts      edit_published_posts      edit_pages      edit_others_pages      edit_published_pages      edit_published_pages      delete_pages      delete_others_pages      delete_published_pages      delete_posts      delete_others_posts      delete_published_posts      delete_private_posts      edit_private_posts      read_private_posts      delete_private_pages      edit_private_pages      read_private_pages      delete_users      create_users      unfiltered_upload      edit_dashboard      update_plugins      delete_plugins Displaying author-related information on posts In a multi-author blog, it's always good for the reader to know the author of the article that they're currently reading. It's even better if they can grab some extra information about the author, such as his website, a short bio, and so on. In this recipe, you'll learn how to edit your single.php theme file to automatically retrieve the author-related information, and display it at the top of the page. Getting ready As we're going to display author information on posts, the first thing to do is to make sure that your contributing authors have entered their biography and other information into the WordPress database. Any author can enter his information by logging in to the WordPress dashboard, and then going to Profile. The blog administrator can edit all of the profiles. The following screenshot shows the WordPress 2.7 profile editor for the authors. How to do it Once you have made sure that your authors have successfully filled their information, you can start coding by carrying out the following steps: Open the file single.php for addition. Paste the following code within the loop: <div id="author-info"><h2>About the author: <?php the_author();?></h2><?php the_author_description(); ?><?php the_author();?>'s website: <a href="<?php the_author_url();?>"><?php the_author_url(); ?></a><br />Other posts by <?php the_author_posts_link(); ?></div><!--/author-info--> Save the file and visit your blog. You will notice that your posts now automatically display the author-related information, as shown in the following screenshot: How it works WordPress provides a dozen of author-related template tags, which are an easy way to retrieve information that is entered by authors in their profile. Note that all of these tags must be used within the loop for them to work. There's more... Here are all the available template tags related to authors:
Read more
  • 0
  • 1
  • 2846

article-image-drools-jboss-rules-50-flow-part-1
Packt
16 Oct 2009
10 min read
Save for later

Drools JBoss Rules 5.0 Flow (Part 1)

Packt
16 Oct 2009
10 min read
Loan approval service Loan approval is a complex process starting with customer requesting a loan. This request comes with information such as amount to be borrowed, duration of the loan, and destination account where the borrowed amount will be transferred. Only the existing customers can apply for a loan. The process starts with validating the request. Upon successful validation, a customer rating is calculated. Only customers with a certain rating are allowed to have loans. The loan is processed by a bank employee. As soon as an approved event is received from a supervisor, the loan is approved and money can be transferred to the destination account. An email is sent to inform the customer about the outcome. Model If we look at this process from the domain modeling perspective, in addition to the model that we already have, we'll need a Loan class. An instance of this class will be a part of the context of this process. The screenshot above shows Java Bean, Loan, for holding loan-related information. The Loan bean defines three properties. amount (which is of type BigDecimal), destinationAccount (which is of type Account; if the loan is approved, the amount will be transferred to this account), and durationYears (which represents a period for which the customer will be repaying this loan). Loan approval ruleflow We'll now represent this process as a ruleflow. It is shown in the following figure. Try to remember this figure because we'll be referring back to it throughout this article. The preceding figure shows the loan approval process—loanApproval.rf file. You can use the Ruleflow Editor that comes with the Drools Eclipse plugin to create this ruleflow. The rest of the article will be a walk through this ruleflow explaining each node in more detail. The process starts with Validate Loan ruleflow group. Rules in this group will check the loan for missing required values and do other more complex validation. Each validation rule simply inserts Message into the knowledge session. The next node called Validated? is an XOR type split node. The ruleflow will continue through the no errors branch if there are no error or warning messages in the knowledge session—the split node constraint for this branch says: not Message() Code listing 1: Validated? split node no errors branch constraint (loanApproval.rf file). For this to work, we need to import the Message type into the ruleflow. This can be done from the Constraint editor, just click on the Imports... button. The import statements are common for the whole ruleflow. Whenever we use a new type in the ruleflow (constraints, actions, and so on), it needs to be imported. The otherwise branch is a "catch all" type branch (it is set to 'always true'). It has higher priority number, which means that it will be checked after the no errors branch. The .rf files are pure XML files that conform with a well formed XSD schema. They can be edited with any XML editor. Invalid loan application form If the validation didn't pass, an email is sent to the customer and the loan approval process finishes as Not Valid. This can be seen in the otherwise branch. There are two nodes-Email and Not Valid. Email is a special ruleflow node called work item. Email work item Work item is a node that encapsulates some piece of work. This can be an interaction with another system or some logic that is easier to write using standard Java. Each work item represents a piece of logic that can be reused in many systems. We can also look at work items as a ruleflow alternative to DSLs. By default, Drools Flow comes with various generic work items, for example, Email (for sending emails), Log (for logging messages), Finder (for finding files on a file system), Archive (for archiving files), and Exec (for executing programs/system commands). In a real application, you'd probably want to use a different work item than a generic one for sending an email. For example, a custom work item that inserts a record into your loan repository. Each work item can take multiple parameters. In case of email, these are: From, To, Subject, Text, and others. Values for these parameters can be specified at ruleflow creation time or at runtime. By double-clicking on the Email node in the ruleflow, Custom Work Editor is opened (see the following screenshot). Please note that not all work items have a custom editor. In the first tab (not visible), we can specify recipients and the source email address. In the second tab (visible), we can specify the email's subject and body. If you look closer at the body of the email, you'll notice two placeholders. They have the following syntax: #{placeholder}. A placeholder can contain any mvel code and has access to all of the ruleflow variables (we'll learn more about ruleflow variables later in this article). This allows us to customize the work item parameters based on runtime conditions. As can be seen from the screenshot above, we use two placeholders: customer.firstName and errorList. customer and errorList are ruleflow variables. The first one represents the current Customer object and the second one is ValidationReport. When the ruleflow execution reaches this email work item, these placeholders are evaluated and replaced with the actual values (by calling the toString method on the result). Fault node The second node in the otherwise branch in the loan approval process ruleflow is a fault node. Fault node is similar to an end node. It accepts one incoming connection and has no outgoing connections. When the execution reaches this node, a fault is thrown with the given name. We could, for example, register a fault handler that will generate a record in our reporting database. However, we won't register a fault handler, and in that case, it will simply indicate that this ruleflow finished with an error. Test setup We'll now write a test for the otherwise branch. First, let's set up the test environment. Then a new session is created in the setup method along with some test data. A valid Customer with one Account is requesting a Loan. The setup method will create a valid loan configuration and the individual tests can then change this configuration in order to test various exceptional cases. @Before public void setUp() throws Exception { session = knowledgeBase.newStatefulKnowledgeSession(); trackingProcessEventListener = new TrackingProcessEventListener(); session.addEventListener(trackingProcessEventListener); session.getWorkItemManager().registerWorkItemHandler( "Email", new SystemOutWorkItemHandler()); loanSourceAccount = new Account(); customer = new Customer(); customer.setFirstName("Bob"); customer.setLastName("Green"); customer.setEmail("bob.green@mail.com"); Account account = new Account(); account.setNumber(123456789l); customer.addAccount(account); account.setOwner(customer); loan = new Loan(); loan.setDestinationAccount(account); loan.setAmount(BigDecimal.valueOf(4000.0)); loan.setDurationYears(2); Code listing 2: Test setup method called before every test execution (DefaulLoanApprovalServiceTest.java file). A tracking ruleflow event listener is created and added to the knowledge session. This event listener will record the execution path of a ruleflow—store all of the executed ruleflow nodes in a list. TrackingProcessEventListener overrides the beforeNodeTriggered method and gets the node to be executed by calling event.getNodeInstance(). loanSourceAccount represents the bank's account for sourcing loans. The setup method also registers an Email work item handler. A work item handler is responsible for execution of the work item (in this case, connecting to the mail server and sending out emails). However, the SystemOutWorkItemHandler implementation that we've used is only a dummy implementation that writes some information to the console. It is useful for our testing purposes. Testing the 'otherwise' branch of 'Validated?' node We'll now test the otherwise branch, which sends an email informing the applicant about missing data and ends with a fault. Our test (the following code) will set up a loan request that will fail the validation. It will then verify that the fault node was executed and that the ruleflow process was aborted. @Test public void notValid() { session.insert(new DefaultMessage()); startProcess(); assertTrue(trackingProcessEventListener.isNodeTriggered( PROCESS_LOAN_APPROVAL, NODE_FAULT_NOT_VALID)); assertEquals(ProcessInstance.STATE_ABORTED, processInstance.getState()); } Code listing 3: Test method for testing Validated? node's otherwise branch (DefaultLoanApprovalServiceTest.java file). By inserting a message into the session, we're simulating a validation error. The ruleflow should end up in the otherwise branch. Next, the test above calls the startProcess method. It's implementation is as follows: private void startProcess() { Map<String, Object> parameterMap = new HashMap<String, Object>(); parameterMap.put("loanSourceAccount", loanSourceAccount); parameterMap.put("customer", customer); parameterMap.put("loan", loan); processInstance = session.startProcess( PROCESS_LOAN_APPROVAL, parameterMap); session.insert(processInstance); session.fireAllRules(); } Code listing 4: Utility method for starting the ruleflow (DefaultLoanApprovalServiceTest.java file). The startProcess method starts the loan approval process. It also sets loanSourceAccount, loan, and customer as ruleflow variables. The resulting process instance is, in turn, inserted into the knowledge session. This will enable our rules to make more sophisticated decisions based on the state of the current process instance. Finally, all of the rules are fired. We're already supplying three variables to the ruleflow; however, we haven't declared them yet. Let's fix this. Ruleflow variables can be added through Eclipse's Properties editor as can be seen in the following screenshot (just click on the ruleflow canvas, this should give the focus to the ruleflow itself). Each variable needs a name type and, optionally, a value. The preceding screenshot shows how to set the loan ruleflow variable. Its Type is set to Object and ClassName is set to the full type name droolsbook.bank.model.Loan. The other two variables are set in a similar manner. Now back to the test from code listing 3. It verifies that the correct nodes were triggered and that the process ended in aborted state. The isNodeTriggered method takes the process ID, which is stored in a constant called PROCESS_LOAN_APPROVAL. The method also takes the node ID as second argument. This node ID can be found in the properties view after clicking on the fault node. The node ID—NODE_FAULT_NOT_VALID—is a constant of type long defined as a property of this test class. static final long NODE_FAULT_NOT_VALID = 21;static final long NODE_SPLIT_VALIDATED = 20; Code listing 5: Constants that holds fault and Validated? node's IDs (DefaultLoanApprovalServiceTest.java file). By using the node ID, we can change node's name and other properties without breaking this test (node ID is least likely to change). Also, if we're performing bigger re-factorings involving node ID changes, we have only one place to update—the test's constants. Ruleflow unit testingDrools Flow support for unit testing isn't the best. With every test, we have to run the full process from start to the end. We'll make it easier with some helper methods that will set up a state that will utilize different parts of the flow. For example, a loan with high amount to borrow or a customer with low rating.Ideally we should be able to test each node in isolation. Simply start the ruleflow in a particular node. Just set the necessary parameters needed for a particular test and verify that the node executed as expected.Drools support for snapshots may resolve some of these issues; however, we'd have to first create all snapshots that we need before executing the individual test methods. Another alternative is to dig deeper into Drools internal API, but this is not recommended. The internal API can change in the next release without any notice.
Read more
  • 0
  • 0
  • 2831
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 ₹800/month. Cancel anytime
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-jboss-portals-and-ajax-part-1
Packt
16 Oct 2009
7 min read
Save for later

JBoss Portals and AJAX - Part 1

Packt
16 Oct 2009
7 min read
Rich user interfaces and AJAX Rich user interfaces can be achieved by using a combination of dynamic HTML elements such as HTML and JavaScript. However, the scope of such an interface is limited to client-side behavior and has minimal functional implications due to the lack of server-side interactions. The power of AJAX is in its capability to provide even richer interface by supplementing its dynamic user interface with powerful functionality through seamless server-side invocation power. AJAX allows individual user interface components to communicate with the server and exchange data without the need for refreshing the whole screen. This is achieved using a process called Web Remoting. Web remoting, or the process of communicating between a browser and a server, can be performed in multiple ways. The popular approaches that are supported by today's browsers are IFrames and XMLHttpRequest. Dynamic HTML can be complemented with either of these methods to generate AJAX functionality. Asynchronous JavaScript and XML or AJAX Asynchronous communication between the client and the server forms the backbone of AJAX. Although an asynchronous request-response method can provide significant value in the development of rich functionality by itself, the results are lot more pronounced when used in conjunction with other functional standards such as CSS, DOM, JavaScript, and so on. The predominant popularity of AJAX stems from such usage. Client-server communication can be achieved either by using IFrames, or by using the supported JavaScript function called XMLHttpRequest(). Due to certain limitations of IFrames, XMLHttpRequest has gained a lot more acceptance. While IFrame can also be an effective option for implementing AJAX-based solutions, in this article, we will focus largely on an XMLHttpRequest-based implementation. The primary advantage of using AJAX-based interfaces is that the update of content occurs without page refreshes. A typical AJAX implementation using XMLHttpRequest happens as described in the following steps: An action on the client side, whether this is a mouse click or a timed refresh, triggers a client event An XMLHttpRequest object is created and configured The XMLHttpRequest object makes a call The request is processed by a server-side component The component returns an XML (or an equivalent) document containing the result The XMLHttpRequest object calls the callback() function and processes the result The HTML DOM is updated with any resulting values The following simplified image illustrates the high-level steps involved in an AJAX request flow. The portal client page gets served to the client browser, where the execution of JavaScript functions takes place. The following example illustrates the initialization of the request object and its basic use: if (window.XMLHttpRequest) // Object of the current window { // for non-IE browsers request = new XMLHttpRequest();}else if (window.ActiveXObject){ // For IE request = new ActiveXObject("Microsoft.XMLHTTP");}request.onreadystatechange = function(){ // do something to process response};if (request.readyState == 4){ // everything received, OK. Do something now..} else { // wait for the response to come to ready state} In subsequent sections, we will modify our sample portal application by adding AJAX functionality to one of the portlets. AJAX in JBoss portal AJAX has gained tremendous popularity in the traditional web application development world due to the richness and agility that it brings to user interfaces. Portals, such as JBoss portal, can also gain significantly from AJAX, in terms of implementation of both behavior and functionality. Refreshing the page content tends to be a time-consuming and resource-intensive process. Every request that a user makes to the server, either by clicking on submissions or links, results in the portal calling doView() and a series of methods for each portlet on the page, one at a time, before aggregating the results and sending the response back to the browser. Using AJAX allows for simultaneous submissions of request in their own independent threads of execution, resulting in an asynchronous and parallel execution. The portal page refresh overhead is now only as long as the time consumed by the slowest portlet. The response times observed by the user improve dramatically, while at the same time allowing more functionality on pages. Architecturally, vertical independent stacks of execution facilitate cleaner and more modular designs and implementations. AJAX can be implemented in JBoss portal in the following two ways: Using in-built support for asynchronous portal behavior by using configurations Writing custom behavior in portlets and page content by using AJAX libraries The in-built support for asynchronous behavior comprises of support for both markup and content. The markup support is in layouts and renderers, while the content is supported through configurable drag-drop and partial page refresh behavior. Almost all of the AJAX behavior supported by JBoss portal relates to asynchronous communication between the client and the portal servers. The only exception is the drag-drop behavior, which is largely view functionality. As far as the custom development within a portlet is concerned, the options are innumerable. A portlet can be developed using many advanced frameworks that are available as either commercial or open source products. For example, user interface features such as drag-and-drops, grids, accordion selects, pull-down menus, content refresh, and so on can be implemented by using third-party libraries including Scriptaculous, JQuery, and DOJO, which have gained a strong following among developers, even on traditional applications and non-portal platforms. In the next few sections, we will walk through an example of AJAX-enabled portlets using one of these libraries, developed on the JBoss portal platform. However, before we go into the implementation, let's step back and understand the limitations that the current portlet specification– JSR-286–addresses, facilitating easy development of AJAX portlets. JSR-168 AJAX limitations Before we look at the features and options provided by the new specification, let's look at how traditional JSR-168 portlets functioned. As shown in the following figure, the "Action" request invoked the processAction method on the server, which implemented controller logic to route it to the correct view. The "Render" request then invokes the render method to serve the content page to the browser. However, when the portlet uses AJAX and needs to makes an asynchronous call, it has to use ActionURL. This in turn follows the standard processing when processAction processes the request and the render method creates the user interface. However, now when the user interface is sent back, the portal injects some other markup and recreates the entire portal page. Hence, instead of refreshing a snippet of user interface, we end up refreshing the whole page. The issues with JSR-168 and AJAX can be broadly summarized as follows: ActionURL and RenderURL point to a portal, and not to a portlet. When we point to a portal, the result is a complete portal page, even if the portlet generates only a snippet. As per the specification, the user interface rendered by the portlet is supposed to be aggregated with some other markup and served back to the browser. When more than only the necessary data and markup is sent back, the JavaScript code on the client side that makes the asynchronous call cannot process the request. Asynchronous calls are made through XMLHttpRequest, which is designed to consume and process the complete response from the portlet. With the portal processing the request in between, XMLHttpRequest cannot consume the original response for processing. This defeats the purpose and value of using asynchronous calls to the server, and we end up with traditional full page refreshes. There were obviously a few workarounds to this. The most common practice was to serve the request from outside of the portal container into the web container. The idea is that the AJAX call can still be made to ActionURL, but the render function copies or shares its context with a traditional Java servlet in the web container of the application server. The AJAX call can now make a direct request to the servlet and get an asynchronous response from the servlet with no interference from the portal. There was a need for a better solution, and one that was incorporated as part of the specification. JSR-286, the latest portlet specification, addresses these problems.
Read more
  • 0
  • 0
  • 2399

article-image-jquery-ui-accordion-widget-part-1
Packt
16 Oct 2009
9 min read
Save for later

jQuery UI Accordion Widget - Part 1

Packt
16 Oct 2009
9 min read
Accordion's structure Let's take a moment to familiarize ourselves with what an accordion is made of. Within the outer container is a series of links. These links are the headings within the accordion and each heading will have a corresponding content panel, or drawer as they are sometimes referred to, which opens when the heading is clicked. The following screenshot shows these elements as they may appear in an accordion: It's worth remembering that when using the accordion widget, only one content panel can be open at any one time. Let's implement a basic accordion now. In a blank page in your text editor, create the following page: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>jQuery UI Accordion Widget Example 1</title> </head> <body> <ul id="myAccordion"> <li> <a href="#">Header 1</a> <div>Wow, look at all this content that can be shown or hidden with a simple click!</div> </li> <li> <a href="#">Header 2</a> <div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpatligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse potenti. </div> </li> <li> <a href="#">Header 3</a> <div>Donec at dolor ac metus pharetra aliquam. Suspendisse purus. Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt viverra felis. Integer elit mauris, egestas ultricies, gravida vitae, feugiat a, tellus.</div> </li> </ul> <script type="text/javascript" src="jqueryui1.6rc2/jquery-1.2.6.js"></script> <script type="text/javascript" src="jqueryui1.6rc2/ui/ui.core.js"></script> <script type="text/javascript" src="jqueryui1.6rc2/ui/ui.accordion.js"></script> <script type="text/javascript"> //function to execute when doc ready $(function() { //turn specified element into an accordion $("#myAccordion").accordion(); }); </script> </body></html> Save the file as accordion1.html in your jqueryui folder and try it out in a browser. We haven't specified any styling at all at this stage, but as you can see from the following screenshot, it still functions exactly as intended: Little code is required for a basic working version of the accordion widget. A simple unordered list element is the mark-up foundation which is transformed by the library into the accordion object. The following three separate external script files are required for an accordion: The jQuery library itself (jquery-1.2.6.js) The UI base file (ui.core.js) The accordion source file (ui.accordion.js) The first two files are mandatory requirements of all components of the UI library. They should be linked to in the order shown here. Each widget also has its own source file, and may depend on other components as well. The order in which these files appear is important. The jQuery library must always appear first, followed by the UI base file. After these files, any other files that the widget depends upon should appear before the widget's own script file. The library components will not function as expected if files are not loaded in the correct order. Finally, we use a custom <script> block to turn our <ul> element into the accordion. We can use the jQuery object shortcut $ to specify an anonymous function which will be executed as soon as the document is ready. This is analogous to using $(document).ready(function(){}) and helps to cut down on the amount of code we have to type. Following this, we use the simple ID selector $("#myAccordion") to specify the element on the page we want to transform. We then use the accordion() constructor method to create the accordion Other elements can be turned into accordions as well. All list element variants are supported including ordered lists and definition lists. You don't even need to base the accordion on a list element at all. You can build a perfectly functional accordion using just nested <div> and <a> elements, although additional configuration will be required In the above example, we used an empty fragment (#) as the value of the href attribute. You should note that any URLs supplied for accordion headers will not be followed when the header is clicked within the accordion when using the default implementation. Styling the accordion With no styling, the accordion will take up 100% of the width of its container. Like with other widgets, we have several options for styling the accordion. We can create our own custom stylesheet to control the appearance of the accordion and its content, we can use the default or flora themes that come with the library, or we can use Theme Roller to create an extensive skin for the whole library. Let's see how using the flora theme for the accordion will cause it to render. In accordion1.html, add the following <link> tag to the <head> of the page: <link rel="stylesheet" type="text/css" href="jqueryui1.6rc2/themes/flora/flora.accordion.css"> Save the new file as accordion2.html, also in the jqueryui folder, and view it again in a browser. It should appear something like this: The accordion theme file assumes that an unordered list is being used as the basis of the widget and specifically targets <li> elements with certain style rules. We can easily create our own custom theme to style the accordion for situations where we want to use a non-list-based accordion widget, or if we simply want different colors or font styles. You can use the excellent Firebug plugin for Firefox, or another DOM viewer, to see the class names that are automatically added to certain elements when the accordion is generated. You can also read through an un-minified version of the source file if you really feel like it. These will be the class names that we'll be targeting with our custom CSS. The following screenshot shows Firebug in action: Change accordion2.html so that it appears as follows (new code is shown in bold): <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html lang="en"> <head> <link rel="stylesheet" type="text/css" href="styles/accordionTheme.css"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>jQuery UI Accordion Widget Example 3</title> </head> <body> <div id="myAccordion"> <span class="corner topLeft"></span><span class="corner topRight"></span><span class="corner bottomLeft"></span><span class="corner bottomRight"></span> <div><a href="#">Header 1</a><div>Wow, look at all this content that can be shown or hidden with a simple click!</div></div> <div><a href="#">Header 2</a><div>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean sollicitudin. Sed interdum pulvinar justo. Nam iaculis volutpatligula. Integer vitae felis quis diam laoreet ullamcorper. Etiam tincidunt est vitae est. Ut posuere, mauris at sodales rutrum, turpis tellus fermentum metus, ut bibendum velit enim eu lectus. Suspendisse potenti.</div></div> <div><a href="#">Header 3</a><div>Donec at dolor ac metus pharetra aliquam. Suspendisse purus. Fusce tempor ultrices libero. Sed quis nunc. Pellentesque tincidunt viverra felis. Integer elit mauris, egestas ultricies, gravida vitae, feugiat a, tellus.</div></div> </div> <script type="text/javascript" src="jqueryui1.6rc2/jquery-1.2.6.js"></script> <script type="text/javascript" src="jqueryui1.6rc2/ui/ui.core.js"></script> <script type="text/javascript" src="jqueryui1.6rc2/ui/ui.accordion.js"></script> <script type="text/javascript"> //function to execute when doc ready $(function() { //turn specified element into an accordion $("#myAccordion").accordion(); }); </script> </body></html> Save this version as accordion3.html in the jqueryui folder. The class name ui-accordion is automatically added to the accordion's container element. Therefore, we can use this as a starting point for most of our CSS selectors. The links that form our drawer headers are given the class ui-accordion-header so we can also target this class name. In a new file, create the following stylesheet: #myAccordion { width:200px; border:2px solid #000000; position:relative; list-style-type:none; padding-left:0;}.ui-accordion-header { text-decoration:none; font-weight:bold; color:#000000; display:block; width:100%; text-align:center;}.ui-accordion div div { font-size:90%;}.ui-accordion a { color:#ffffff; background:url(../img/accordion/header-sprite.gif) repeat-x 0px 0px;}.ui-accordion a.selected { background:url(../img/accordion/header-sprite.gif) repeat-x 0px -22px;}.ui-accordion a:hover { background:url(../img/accordion/header-sprite.gif) repeat-x 0px -44px;}/* container rounded corners */.corner { position:absolute; width:12px; height:13px; background:url(../img/accordion/corner-sprite.gif) no-repeat;}.topLeft { top:-2px; left:-2px; background-position:0px 0px;}.topRight { top:-2px; right:-2px; background-position:0px -13px;}.bottomRight { bottom:-2px; right:-2px; background-position:0px -26px;}.bottomLeft { bottom:-2px; left:-2px; background-position:0px -39px;} Save this file as accordionTheme.css in your styles folder and preview accordion3.html in a browser. We will need a new folder for the images we use in this and subsequent examples. Create a new folder inside the img folder and name it accordion. With just two images, and a few simple style rules, we can drastically change the default appearance of the accordion with our own custom skin as shown in the following screenshot: Configuring accordion The accordion has a range of configurable properties which allow us to easily change the default behaviour of the widget. The following table lists the available properties, their default value, and gives a brief description of their usage:
Read more
  • 0
  • 0
  • 4496

article-image-extending-opencms-developing-custom-widget
Packt
16 Oct 2009
8 min read
Save for later

Extending OpenCms: Developing a Custom Widget

Packt
16 Oct 2009
8 min read
Structured Content Types Support for structured content is a key feature of OpenCms. Structured content types allow different templates to be used to re-skin a site, or to share content with other sites that have a different look. Structured content types are defined by creating XSD schemas and placing them into modules. Once a new content type has been defined, the Workplace Explorer provides a user interface to create new instances of the content and allows it to be edited. There are some sample content types and templates that come with the Template One group of modules. These content types are very flexible and allow a site to be built using them right away. However, they may not fit our site requirements. In general, site requirements and features will determine the design of the structured content types and templates that need to be developed. BlogEntry Content Type For designing a blog website it is required that the content type contains blog entries. The schema file for the BlogEntry content type looks like the following : <!-- ======================================================== Content definition schema for the BlogEntry type ========================================================== --> <!-- 1. Root Element --> <xsd:schema elementFormDefault="qualified"> <!-- 2. Define the location of the schema location --> <xsd:include schemaLocation="opencms://opencms-xmlcontent.xsd"/> <!-- 3. Root element name and type of our XML type --> <xsd:element name="BlogEntrys" type="OpenCmsBlogEntrys"/> <!-- 4. Definition of the type described above --> <xsd:complexType name="OpenCmsBlogEntrys"> <xsd:sequence> <xsd:element name="BlogEntry" type="OpenCmsBlogEntry" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <!-- 5. Data field definitions --> <xsd:complexType name="OpenCmsBlogEntry"> <xsd:sequence> <xsd:element name="Title" type="OpenCmsString" minOccurs="1" maxOccurs="1" /> <xsd:element name="Date" type="OpenCmsDateTime" minOccurs="1" maxOccurs="1" /> <xsd:element name="Image" type="OpenCmsVfsFile" minOccurs="0" maxOccurs="1" /> <xsd:element name="Alignment" type="OpenCmsString" minOccurs="1" maxOccurs="1" /> <xsd:element name="BlogText" type="OpenCmsHtml" minOccurs="1" maxOccurs="1" /> <xsd:element name="Category" type="OpenCmsString" minOccurs="0" maxOccurs="10" /> </xsd:sequence> <!-- 6. locale attribute is required --> <xsd:attribute name="language" type="OpenCmsLocale" use="required"/> </xsd:complexType> <!—optional code section --> <xsd:annotation> <xsd:appinfo> <!-- Mappings allow data fields to be mapped to content properties --> <mappings> <mapping element="Title" mapto="property:Title" /> <mapping element="Date" mapto="attribute:datereleased" /> </mappings><!-- Validation rules for fields --> <validationrules> <rule element="BlogText" regex="!.*[Bl]og.*" type= "warning" message="${key.editor.warning.BlogEntry. dontallowblog|${validation.path}}"/> </validationrules> <!-- Default values for fields --> <defaults> <default element="Date" value="${currenttime}"/> <default element="Alignment" value="left"/> </defaults> <!-- user interface widgets for data fields --> <layouts> <layout element="Image" widget="ImageGalleryWidget"/> <layout element="Alignment" widget="SelectorWidget" configuration="left|right|center" /> <layout element="Category" widget="SelectorWidget" configuration="silly|prudent|hopeful|fearful| worrisome|awesome" /> <layout element="BlogText" widget="HtmlWidget"/> </layouts> <!-- UI Localization --> <resourcebundle name="com.deepthoughts.templates.workplace"/> <!-- Relationship checking --> <relations> <relation element="Image" type="strong" invalidate="node" /> </relations> <!-- Previewing URI --> <preview uri="${previewtempfile}" /> <!-- Model Folder for content models --> <modelfolder uri="/system/modules/com.deepthoughts.templates /defaults/" /> </xsd:appinfo> </xsd:annotation> </xsd:schema> The BlogEntry content type file is named as blogentry.xsd and it placed in the folder named schemas in modules. Designing a Custom Widget Referring to the highlighted code in BlogEntry content type schema file we can see that the category field is populated from a drop-down list provided by SelectorWidget. The SelectorWidget obtains its values from the static configuration string defined within the blog schema file. This design is problematic as we would like category values to be easily changed or added. Ideally, the list of category values should be able to be updated by site content editors. Fortunately, we can create our own custom widget to handle this requirement. An OpenCms widget is a Java class that implements the I_CmsWidget interface, located in the org.opencms.widgets package. The interface contains a number of methods that must be implemented. First there are some methods dealing with instantiation and configuration of the widget: newInstance: This returns a new instance of the widget. setConfiguration: This method is called after the widget has been initialized to configure it. The configuration information is passed as a string value coming from the declaration of the widget within the schema file of the content type using it. getConfiguration: This is called to retrieve the configuration information for the widget. Next, there are some methods used to handle the rendering. These methods are called by widget enabled dialogs that might be used in a structured content editor or an administration screen. The methods provide any Javascript, CSS, or HTML needed by the widget dialogs: getDialogIncludes: This method is called to retrieve any Javascript or CSS includes that may be used by the widget. getDialogInitCall: This method may return Javascript code that performs initialization or makes calls to other Javascript initialization methods needed by the widget. getDialogInitMethod: This method may return Javascript code containing any functions needed by the widget. getDialogHtmlEnd: This method is called at the end of the dialog and may be used to return an HTML or Javascript needed by the widget. getDialogWidget: This method returns the actual HTML and Javascript used to render the widget along with its values. getHelpBubble: This method returns the HTML for displaying the help icon relating to this widget. getHelpText: This method returns the HTML for displaying the help text relating to this widget. Lastly, there are some methods used to get and set the widget value: getWidgetStringValue: This method returns the value selected from the widget. setEditorValue: This method sets the value into the widget. All these methods have base implementations in the A_CmsWidget class. In most cases, the base methods do not need to be overridden. As such, we will not cover all the methods in detail. If it is necessary to override the methods, the best way to get an idea of how to implement them is to look at the code using them. All widgets are used in dialog boxes which have been enabled for widgets, by implementing the I_CmsWidgetDialog interface. There are two general instances of these dialogs, one is used for editing structured XML content, the other is found in any dialog appearing in the Administration View. The two classes implementing this interface are: org.opencms.workplace.CmsWidgetDialog org.opencms.workplace.editors.CmsXmlContentEditor The CmsWidgetDialog class is itself a base class, which is used by all dialogs found in the Administrative View. Before designing a new widget, it is useful to examine the existing widget code. The default OpenCms widgets can be found in the org.opencms.widgets package. All the widgets in this package subclass the A_CmsWidget class mentioned earlier. Often, a new widget design may be subclassed from an existing widget. Designing the Widget As mentioned earlier, we would like to have a widget that obtains its option data values dynamically rather than from a fixed configuration string value. Rather than create a widget very specific to our needs, we will use a flexible design where the data source location can be specified in the configuration parameter. The design will allow for other data sources to be plugged into the widget. This way, we can use a single widget to obtain dynamic data from a variety of sources. To support this design, we will use the configuration parameter to contain the name of a Java class used as a data source. The design will specify a pluggable data source through a Java interface that a data source must implement. Furthermore, a data source can accept parameters via the widget configuration string. With this design, an example declaration for a widget named CustomSourceSelectWidget would look like this: <layout element="Category" widget="CustomSourceSelectWidget" configuration="source='com.widgets.sources.MySource'| option1='some config param'| option2='another param'" /> This declaration would appear in the schema of a content type, using the widget as covered earlier. The configuration parameter consists of name/value pairs, delimited by the vertical bar character. Each name/value pair is separated by the equal to sign and the value is always enclosed in single quotes. The design requires that at least the source parameter be specified. Additional parameters will depend upon the specific data source being used. The example declaration specifies that the data field named Category will use the CustomSourceSelectWidget widget for its layout. The configuration parameter contains the name of the Java class to be used to obtain the data source. The data source will receive the two parameters named option1 and option2 along with their values. Next, lets move on to the code to see how this all gets implemented.
Read more
  • 0
  • 0
  • 2519
article-image-primer-agi-asterisk-gateway-interface
Packt
16 Oct 2009
2 min read
Save for later

A Primer to AGI: Asterisk Gateway Interface

Packt
16 Oct 2009
2 min read
How does AGI work Let's examine the following diagram: As the previous diagram illustrates, an AGI script communicates with Asterisk via two standard data streams—STDIN (Standard Input) and STDOUT (Standard Output). From the AGI script point-of-view, any input coming in from Asterisk would be considered STDIN, while output to Asterisk would be considered as STDOUT. The idea of using STDIN/STDOUT data streams with applications isn't a new one, even if you're a junior level programmer. Think of it as regarding any input from Asterisk with a read directive and outputting to Asterisk with a print or echo directive. When thinking about it in such a simplistic manner, it is clear that AGI scripts can be written in any scripting or programming language, ranging from BASH scripting, through PERL/PHP scripting, to even writing C/C++ programs to perform the same task. Let's now examine how an AGI script is invoked from within the Asterisk dialplan: exten => _X.,1,AGI(some_script_name.agi,param1,param2,param3) As you can see, the invocation is similar to the invocation of any other Asterisk dialplan application. However, there is one major difference between a regular dialplan application and an AGI script—the resources an AGI script consumes.While an internal application consumes a well-known set of resources from Asterisk, an AGI script simply hands over the control to an external process. Thus, the resources required to execute the external AGI script are now unknown, while at the same time, Asterisk consumes the resources for managing the execution of the AGI script.Ok, so BASH isn't much of a resource hog, but what about Java? This means that the choice of programming language for your AGI scripts is important. Choosing the wrong programming language can often lead to slow systems and in most cases, non-operational systems. While one may argue that the underlying programming language has a direct impact on the performance of your AGI application, it is imperative to learn the impact of each. To be more exact, it's not the language itself, but more the technology of the programming language runtime that is important. The following table tries to distinguish between three programming languages' families and their applicability to AGI development.
Read more
  • 0
  • 0
  • 6544

article-image-windows-development-using-visual-studio-2008
Packt
16 Oct 2009
11 min read
Save for later

Windows Development Using Visual Studio 2008

Packt
16 Oct 2009
11 min read
Visual Studio Visual Studio is an environment for developing applications in Windows. It has a number of tools, such as an editor, compilers, linkers, a debugger, and a project manager. It also has several Wizards—tools designed for rapid development. The Wizard you will first encounter is the Application Wizard. It generates code for an Application Framework. The idea is that we use the Application Wizard to design a skeleton application that is later completed with more application-specific code. There is no real magic about wizards, all they do is generate the skeleton code. We could write the code ourselves, but it is a rather tedious job. Moreover, an application can be run in either debug or release mode. In debug mode, additional information is added in order to allow debugging; in release mode, all such information is omitted in order to make the execution as fast as possible. The code of this article is developed with Visual Studio 2008. The Windows 32 bits Application Programming Interface (Win32 API) is a huge C function library. It contains a couple of thousand functions for managing the Windows system. With the help of Win32 API it is possible to totally control the Windows operating system. However, as the library is written in C, it could be a rather tedious job to develop a large application, even though it is quite possible. That is the main reason for the existence of the Microsoft Foundation Classes (MFC). It is a large C++ class library containing many classes encapsulating the functionality of Win32 API. It does also hold some generic classes to handle lists, maps, and arrays. MFC combines the power of Win32 API with the advantages of C++. However, on some occasions MFC is not enough. When that happens, we can simply call an appropriable Win32 API function, even though the application is written in C++ and uses MFC. Most of the classes of MFC belong to a class hierarchy with CObject at the top. On some occasions, we have to let our classes inherit CObject in order to achieve some special functionality. The baseclass Figure in the Draw and Tetris applications inherits CObject in order to read or write objects of unknown classes. The methods UpdateAllViews and OnUpdate communicate by sending pointers to CObject objects. The Windows main class is CWnd. In this environment, there is no function main. Actually, there is a main, but it is embedded in the framework. We do not write our own main function, and there is not one generated by the Application Wizard. Instead, there is the object theApp, which is an instance of the application class. The application is launched by its constructor. When the first version of MFC was released, there was no standard logical type in C++. Therefore, the type BOOL with the values TRUE and FALSE was introduced. After that, the type bool was introduced to C++. We must use BOOL when dealing with MFC method calls, and we could use bool otherwise. However, in order to keep things simple, let us use BOOL everywhere. In the same way, there is a MFC class CString that we must use when calling MFC methods. We could use the C++ built-in class string otherwise. However, let us use CString everywhere. The two classes are more or less equivalent. There are two types for storing a character, char and wchar_t. In earlier version of Windows, you were supposed to use char for handling text, and in more modern versions you use wchar_t. In order to make our application independent of which version it is run on, there are two macros TCHAR and TEXT. TCHAR is the character type that replaces char and wchar_t. TEXT is intended to encapsulate character and string constants. TCHAR *pBuffer;stScore.Format(TEXT("Score: %d."), iScore); There is also the MFC type BYTE which holds a value of the size of one byte, and UINT which is shorthand for unsigned integer. Finally, all generated framework classes have a capital C at the beginning of the name. The classes we write ourselves do not. The Document/View model The applications in this article are based on the Document/View model. Its main idea is to have two classes with different responsibilities. Let us say we name the application Demo, the Application Wizard will name the document class CDemoDoc and the view class will be named CDemoView. The view class has two responsibilities: to accept input from the user by the keyboard or the mouse, and to repaint the client area (partly or completely) at the request of the document class or the system. The document's responsibility is mainly to manage and modify the application data. The model comes in two forms: Single Document Interface (SDI) and Multiple Document Interface (MDI). When the application starts, a document object and a view object are created, and connected to each other. In the SDI, it will continue that way. In the MDI form, the users can then add or remove as many views they want to. There is always exactly one document object, but there may be one or more view objects, or no one at all. The objects are connected to each other by pointers. The document object has a list of pointers to the associated view objects. Each view object has a fieldm_pDocument that points at the document object. When a change in the document's data has occurred, the document instructs all of its views to repaint their client area by calling the method UpdateAllViews in order to reflect the change. The message system Windows is built on messages. When the users press one of the mouse buttons or a key, when they resize a window, or when they select a menu item, a message is generated and sent to the current appropriate class. The messages are routed by a message map. The map is generated by the Application Wizard. It can be modified manually or with the Properties Window View (the Messages or Events button). The message map is declared in the file class' header file as follows: DECLARE_MESSAGE_MAP() The message map is implemented in the class' implementation file as follows: BEGIN_MESSAGE_MAP(this_class, base_class)// Message handlers.END_MESSAGE_MAP() Each message has it own handle, and is connected to a method of a specific form that catches the message. There are different handlers for different types of messages. There are around 200 messages in Windows. Here follows a table with the most common ones. Note that we do not have to catch every message. We just catch those we are interested in, the rest will be handled by the framework. Message Handler/Method Sent WM_CREATE ON_WM_CREATE/OnCreate When the window is created, but not yet showed. WM_SIZE ON_WM_SIZE/OnSize When the window has been resized. WM_MOVE ON_WM_MOVE/OnMove When the window has been moved. WM_SETFOCUS ON_WM_SETFOCUS/ OnSetFocus When the window receives input focus. WM_KILLFOCUS ON_WM_KILLFOCUS/ OnKillFocus When the window loses input focus. WM_VSCROLL ON_WM_VSCROLL/ OnVScroll When the user scrolls the vertical bar. WM_HSCROLL ON_WM_HSCROLL/ OnHScroll When the user scrolls the horizontal bar. WM_LBUTTONDOWN   WM_MBUTTONDOWN   WM_RBUTTONDOWN ON_WM_LBUTTONDOWN/ OnLButtonDown ON_WM_MBUTTONDOWN/ OnMButtonDown ON_WM_RBUTTONDOWN/ OnRButtonDown When the user presses the left, middle, or right mouse button. WM_MOUSEMOVE ON_WM_MOUSEMOVE/ OnMouseMove When the user moves the mouse, there are flags available to decide whether the buttons are pressed. WM_LBUTTONUP   WM_MBUTTONUP   WM_RBUTTONUP ON_WM_LBUTTONUP/ OnLButtonUp ON_WM_MUTTONUP/ OnMButtonUp ON_WM_RUTTONUP/ OnRButtonUp When the user releases the left, middle, or right button. WM_CHAR ON_WM_CHAR/OnChar When the user inputs a writable character of the keyboard. WM_KEYDOWN ON_WM_KEYDOWN/ OnKeyDown When the user presses a key of the keyboard. WM_KEYUP ON_WM_KEYUP/ OnKeyUp When the user releases a key of the keyboard. WM_PAINT ON_WM_PAINT/OnPaint When the client area of the window needs to be repainted, partly or completely. WM_CLOSE ON_WM_CLOSE/OnClose When the user clicks at the close button in the upper right corner of the window. WM_DESTROY ON_WM_DESTROY/ OnDestroy When the window is to be closed. WM_COMMAND ON_COMMAND(Identifier, Name)/OnName   When the user selects a menu item, a toolbar button, or a accelerator key connected to the identifier. WM_COMMAND_ UPDATE ON_COMMAND_ UPDATE_UI(Identifier, Name)/OnUpdateName On idle time, when the system is not busy with any other task, this message is sent in order to enable/disable or to check menu items and toolbar buttons. When a user selects a menu item, a command message is sent to the application. Thanks to MFC, the message can be routed to virtually any class in the application. However, in the applications of this article, all menu messages are routed to the document class. It is possible to connect an accelerator key or a toolbar button to the same message, simply by giving it the same identity number. Moreover, when the system is in idle mode (not busy with any other task) thecommand update message is sent to the application. This gives us an opportunity to check or disable some of the menu items. For instance, the Save item in the File menu should be grayed (disabled) when the document has not been modified and does not have to be saved. Say that we have a program where the users can paint in one of three colors. The current color should be marked by a radio box. The message map and its methods can be written manually or be generated with the Resource View (the View menu in Visual Studio) which can help us generate the method prototype, its skeleton definition, and its entry in the message map. The Resource is a system of graphical objects that are linked to the application. When the framework is created by the Application Wizard, the standard menu bar and toolbar are included. We can add our own menus and buttons in Resource Editor, a graphical tool of Visual Studio. The coordinate system In Windows, there are device (physical) and logical coordinates. There are several logical coordinate mapping systems in Windows. The simplest one is the text system; it simply maps one physical unit to the size of a pixel, which means that graphical figures will have different size monitors with different sizes or resolutions. This system is used in the Ring and Tetris applications. The metric system maps one physical unit to a tenth of a millimeter (low metric) or a hundredth of a millimeter (high metric). There is also the British system that maps one physical unit to a hundredth of an inch (low English) or a thousandth of an inch (high English). The British system is not used in this article. The position of a mouse click is always given in device units. When a part of the client area is invalidated (marked for repainting), the coordinates are also given in device units, and when we create or locate the caret, we use device coordinates. Except for these events, we translate the positions into logical units of our choice. We do not have to write translation routines ourselves, there are device context methods LPtoDP (Logical Point to Device Point) and DPtoLP (Device Point to Logical Point) in the next section that do the job for us. The setting of the logical unit system is done in OnInitialUpdate and OnPrepareDC in the view classes. In the Ring and Tetris Applications, we just ignore the coordinates system and use pixels. In the Draw application, the view class is a subclass of the MFC class CScrollView. It has a method SetScrollSizes that takes the logical coordinate system and the total size of the client area (in logical units). Then the mapping between the device and logical system is done automatically and the scroll bars are set to appropriate values when the view is created and each time its size is changed. void SetScrollSizes(int nMapMode, CSize sizeTotal, const CSize& sizePage = sizeDefault, const CSize& sizeLine = sizeDefault); In the Calc and Word Applications, however, we set the mapping between the device and logical system manually by overriding the OnPrepareDC method. It calls the method SetMapMode which sets the logical horizontal and vertical units to be equal. This ensures that circles will be kept round. The MFC device context method GetDeviceCaps returns the size of the screen in pixels and millimeters. Those values are used in the call to SetWindowExt and SetViewportExt, so that the logical unit is one hundredth of a millimeter also in those applications. The SetWindowOrg method sets the origin of the view's client area in relation to the current positions of the scroll bars, which implies that we can draw figures and text without regarding the current positions of the scroll bars. int SetMapMode(int iMapMode);int GetDeviceCaps(int iIndex) const;CSize SetWindowExt(CSize szScreen);CSize SetViewportExt(CSize szScreen);CPoint SetWindowOrg(CPoint ptorigin);
Read more
  • 0
  • 0
  • 1876

article-image-simplifying-parallelism-complexity-c
Packt
16 Oct 2009
7 min read
Save for later

Simplifying Parallelism Complexity in C#

Packt
16 Oct 2009
7 min read
Specializing the algorithms for segmentation with classes So far, we have been developing applications that split work into multiple independent jobs and created classes to generalize the algorithms for segmentation. We simplified the creation of segmented and parallelized algorithms, generalizing behaviors to simplify our code and to avoid repeating the same code on every new application. However, we did not do that using inheritance, a very powerful object-oriented capability that simplifies code re-use. C# is an object-oriented programming language that supports inheritance and offers many possibilities to specialize behaviors to simplify our code and to avoid some synchronization problems related to parallel programming. How can we use C# object-oriented capabilities to define specific segmented algorithms prepared for running each piece in an independent thread using ParallelAlgorithm and ParallelAlgorithmPiece as the base classes? The answer is very simple—by using inheritance and the factory method class creational pattern (also known as virtual constructor). Thus, we can advance into creating a complete framework to simplify the algorithm optimization process. Again, we can combine multithreading with object-oriented capabilities to reduce our development time and avoid synchronization problems. Besides, using classes to specialize the process of splitting a linear algorithm into many pieces will make it easier for the developers to focus on generating very independent parts that will work well in a multithreading environment, while avoiding side-effects. Time for action – Preparing the parallel algorithm classes for the factory method You made the necessary changes to the ParallelAlgorithmPiece and the ParallelAlgorithm classes to possibly find planets similar to Mars in the images corresponding to different galaxies. NASA's CIO was impressed with your parallel programming capabilities. Nevertheless, he is an object-oriented guru, and he gave you the advice to apply the factory method pattern to specialize the parallel algorithm classes in each new algorithm. That could make the code simpler, more re-usable, and easier to maintain. He asked you to do so. The NASA scientists would then bring you another huge image processing challenge for your parallel programming capabilities—a sunspot analyzer. If you resolve this problem using the factory method pattern or something like that, he will hire you! However, be careful, because you must avoid some synchronization problems! First, we are going to create a new project with tailored versions of the ParallelAlgorithmPiece and ParallelAlgorithm classes. This way, later, we will be able to inherit from these classes and apply the factory method pattern to specialize in parallel algorithms: Create a new C# Project using the Windows Forms Application template in Visual Studio or Visual C# Express. Use SunspotsAnalyzer as the project's name. Open the code for Program.cs. Replace the line [STAThread] with the following line (before the Main method declaration): [MTAThread] Copy the file that contains the original code of the ParallelAlgorithmPiece and the ParallelAlgorithm classes (ParallelAlgorithm.cs) and include them in the project. Add the abstract keyword before the declarations of theParallelAlgorithmPiece and the ParallelAlgorithm classes, as shown in the following lines (we do not want to create instances directly from these abstract classes): abstract class ParallelAlgorithmPieceabstract class ParallelAlgorithm Change the ThreadMethod method declaration in the ParallelAlgorithmPiece class (add the abstract keyword to force us to override it in subclasses): public abstract void ThreadMethod(object poThreadParameter); Add the following public abstract method to create each parallel algorithm piece in the ParallelAlgorithm class (the key to the factory method pattern): public abstract ParallelAlgorithmPieceCreateParallelAlgorithmPiece(int priThreadNumber); Add the following constructor with a parameter to the ParallelAlgorithmPiece class: public ParallelAlgorithmPiece(int priThreadNumberToAssign){priThreadNumber = priThreadNumberToAssign;} Copy the original code of the ParallelAlgorithmPiece class CreatePieces method and paste it in the ParallelAlgorithm class (we move it to allow creation of parallel algorithm pieces of different subclasses). Replace the lloPieces[i].priBegin and lloPieces[i].priEnd private variables' access with their corresponding public properties access lloPieces[i].piBegin and lloPieces[i].piEnd. Change the new CreatePieces method declaration in the ParallelAlgorithm class (remove the static clause and add the virtual keyword to allow us to override it in subclasses and to access instance variables): public virtual List<ParallelAlgorithmPiece>CreatePieces(long priTotalElements, int priTotalParts) Replace the line lloPieces[i] = new ParallelAlgorithmPiece(); in the CreatePieces method declaration in the ParallelAlgorithm class with the following line of code (now the creation is encapsulated in a method, and also, a great bug is corrected, which we will explain later): lloPieces.Add(CreateParallelAlgorithmPiece(i)); Comment the following line of code in the CreatePieces method in the ParallelAlgorithm class (now the new ParallelAlgorithmPiece constructor assigns the value to piThreadNumber): //lloPieces[i].piThreadNumber = i; Replace the line prloPieces = ParallelAlgorithmPiece. CreatePieces(priTotalElements, priTotalParts); in the CreateThreads method declaration in the ParallelAlgorithm class with the following line of code (now the creation is done in the new CreatePieces method): prloPieces = CreatePieces(priTotalElements, priTotalParts); Change the StartThreadsAsync method declaration in the ParallelAlgorithm class (add the virtual keyword to allow us to override it in subclasses): public virtual void StartThreadsAsync() Change the CollectResults method declaration in the ParallelAlgorithm class (add the abstract keyword to force us to override it in subclasses): public abstract void CollectResults(); What just happened? The code required to create subclasses to implement algorithms, following a variation of the factory method class creational pattern, is now held in the ParallelAlgorithmPiece and ParallelAlgorithm classes. Thus, when we create new classes that will inherit from these two classes, we can easily implement a parallel algorithm. We must just fill in the gaps and override some methods, and we can then focus on the algorithm problems instead of working hard on the splitting techniques. We also solved some bugs related to the previous versions of these classes. Using C# programming language's excellent object-oriented capabilities, we can avoid many problems related to concurrency and simplify the development process using high-performance parallel algorithms. Nevertheless, we must master many object-oriented design patterns to help us in reducing the complexity added by multithreading and concurrency. Defining the class to instantiate One of the main problems that arise when generalizing an algorithm is that the generalized code needed to coordinate the parallel algorithm must create instances of the subclasses that represent the pieces. Using the concepts introduced by the factory method class creational pattern, we solved this problem with great simplicity. We made the necessary changes to the ParallelAlgorithmPiece and ParallelAlgorithm classes to implement a variation of this design pattern. First, we added a constructor to the ParallelAlgorithmPiece class with the thread or piece number as a parameter. The constructor assigns the received value to the priThreadNumber private variable, accessed by the piThreadNumber property: public ParallelAlgorithmPiece(int priThreadNumberToAssign){priThreadNumber = priThreadNumberToAssign;} The subclasses will be able to override this constructor to add any additional initialization code. We had to move the CreatePieces method from the ParallelAlgorithmPiece class to the ParallelAlgorithm class. We did this because each ParallelAlgorithm subclass will know which ParallelAlgorithmPiece subclass to create for each piece representation. Thus, we also made the method virtual, to allow it to be overridden in subclasses. Besides, now it is an instance method and not a static one. There was an intentional bug left in the previous CreatePieces method. As you must master lists and collections management in C# in order to master parallel programming, you should be able to detect and solve this little problem. The method assigned the capacity, but did not add elements to the list. Hence, we must use the add method using the result of the new CreateParallelAlgorithmPiece method. lloPieces.Add(CreateParallelAlgorithmPiece(i)); The creation is now encapsulated in this method, which is virtual, and allows subclasses to override it. The original implementation is shown in the following lines: public virtual ParallelAlgorithmPiece CreateParallelAlgorithmPiece(int priThreadNumber){return (new ParallelAlgorithmPiece(priThreadNumber));} It returns a new ParallelAlgorithmPiece instance, sending the thread or piece number as a parameter. Overriding this method, we can return instances of any subclass of ParallelAlgorithmPiece. Thus, we let the ParallelAlgorithm subclasses decide which class to instantiate. This is the principle of the factory method design pattern. It lets a class defer instantiation to subclasses. Hence, each new implementation of a parallel algorithm will have its new ParallelAlgorithm and ParallelAlgorithmPiece subclasses. We made additional changes needed to keep conceptual integrity with this new approach for the two classes that define the behavior of a parallel algorithm that splits work into pieces using multithreading capabilities.
Read more
  • 0
  • 0
  • 2494
article-image-displaying-sql-server-data-using-linq-data-source
Packt
16 Oct 2009
2 min read
Save for later

Displaying SQL Server Data using a Linq Data Source

Packt
16 Oct 2009
2 min read
Create web site project and add LinqDataSource control Open Visual Studio 2008 from its shortcut on the desktop. Click File | New | Web Site...(or Shift+Alt+N) to open the New Web Site window. Change the default name of the site to a name of your choice (herein LinqDemo)on your local web server as shown. Make sure you are creating a .NET Framework 3.5 web site as shown here. Drag and drop a LinqDataSource control from Toolbox|Data shown in the next figure on to the Default.aspx This creates an instance of the control LinqDataSource1 as shown. The figure also shows the smart tasks of this control as shown. Create a data context for the LinqDataSource control In order to use this control you also need to create a data context. Right click the localhost web site and choose Add New Item...to open the Add New Item - http://localhost/ LinqDemo window as shown. In the Visual Studio installed templates highlight Linq to SQL Classes. Change the default name from DataClasses.dbml to a name of your choosing. Herein MyDC.dbml. Click Add. This pops-up a Microsoft Visual Studio warning message as shown. The preferred location for this file is in the App_Code folder of your project as suggested here. Click on Yes. This adds a MyDC.dbml file to APP_Code folder as shown. MyDC.dbml consists of two components MyDC.dbml and MyDC.designer.vb to the App_Code folder as shown . Double click the MyDC.dbml node in the APP_Code folder. This opens the ObjectRelational Designer and the designer surface with two panes as shown. Read the instructions in the windows. In the left pane you can drag and drop items from the Server Explorer in Visual Studio to create the appropriate classes and in the right pane you can drag and drop stored procedures. In this article we will be looking at just creating classes from table objects.
Read more
  • 0
  • 0
  • 3888

article-image-flex-101-flash-builder-4-part-1
Packt
16 Oct 2009
11 min read
Save for later

Flex 101 with Flash Builder 4: Part 1

Packt
16 Oct 2009
11 min read
  The article is intended towards developers who have never used Flex before and would like to exercise a “Hello World” kind of tutorial. The article does not aim to cover Flex and FB4 in detail but rather focuses on the mechanics of FB4 and getting an application running with minimal effort. For developers familiar with Flex and the predecessor to Flash Builder 4 (Flex Builder 2 or 3), it contains an introduction to FB4 and some differences in the way you go about building Flex Applications using FB4. Even if you have not programmed before and are looking at understanding how to make a start in developing applications, this would serve as a good start. The Flex Ecosystem The Flex ecosystem is a set of libraries, tools, languages and a deployment runtime that provides an end-to-end framework for designing, developing and deploying RIAs. All these together are being branded as a part of the Flash platform. In its latest release, Flex 4, special efforts have been put in to address the designer to developer workflow by letting graphic designers address layout, skinning, effects and general look and feel of your application and then the developers taking over to address the application logic, events, etc. To understand this at a high level, take a look at the diagram shown below. This is a very simplified diagram and the intention is to project a 10,000 ft view of the development, compilation and execution process. Let us understand the diagram now: The developer will typically work in the Flash Builder Application. Flash Builder is the Integrated Development Environment (IDE) that provides an environment for coding, compiling, running / debugging your Flex based applications. Your Flex Application will typically consist of MXML and ActionScript code. ActionScript is an ECMAScript compatible Object Oriented language, whereas MXML is an XML-based markup language. Using MXML you can define/layout your visual components like buttons, combobox, data grids, and others. Your application logic will be typically coded inside ActionScript classes/methods. While coding your Flex Application, you will make use of the Flex framework classes that provide most of the core functionality. Additional libraries like Flex Charting libraries and 3rd party components can be used in your application too. Flash Builder compiles all of this into object byte code that can be executed inside the Flash Player. Flash Player is the runtime host that executes your application. This is high level introduction to the ecosystem and as we work through the samples later on in the article, things will start falling into place. Flash Builder 4 Flash Builder is the new name for the development IDE previously known as Flex Builder. The latest release is 4 and it is currently in public beta. Flash Builder 4 is based on the Eclipse IDE, so if you are familiar with Eclipse based tools, you will be able to navigate your way quite easily. Flash Builder 4 like Flex Builder 3 previously is a commercial product and you need to purchase a development license. FB4 currently is in public beta and is available as a 30-day evaluation. Through the rest of the article, we will make use of FB4 and will be focused completely on that to build and run the sample applications. Let us now take a look at setting up FB4. Setting up your Development Environment To setup Flash Builder 4, follows these steps: The first step should be installing Flash Player 10 on your system. We will be developing with the Flex 4 SDK that comes along with Flash Builder 4 and it requires Flash Player 10. You can download the latest version of Flash Player from here: http://www.adobe.com/products/flashplayer/ Download Flash Builder 4 Public Beta from http://labs.adobe.com/technologies/flashbuilder4/. The page is shown below: After you download, run the installer program and proceed with the rest of the installation. Launch the Adobe Flash Builder Beta. It will prompt first with a message that it is a Trial version as shown below: To continue in evaluation mode, select the option highlighted above and click Next. This will launch the Flash Builder IDE. Let us start coding with Flash Builder 4 IDE. We will stick to tradition and write the “Hello World” application. Hello World using Flash Builder 4 In this section, we will be developing a basic Hello World application. While the application does not do much, it will help you get comfortable with the Flash Builder IDE. Launch the Flash Builder IDE. We will be creating a Flex Project. Flash Builder will help us create the Project that will contain all our files. To create a new Flex Project, click on the File → New → Flex Project as shown below: This will bring up a dialog in which you will need to specify more details about the Flex Project that you plan to develop. The dialog is shown below: You will need to provide at least the following information: Project Name: This is the name of your project. Enter a name that you want over here. In our case, we have named our project MyFirstFB4App. Application Type: We can develop both a Web version and a desktop version of our application using Flash Builder. The web application will then run inside of a web browser and execute within the Flash Player plug-in. We will go with the Web option over here. The Desktop application runs inside the Adobe Integrated Runtime environment and can have more desktop like features. We will skip that option for now. We will let the other options remain as is. We will use the Flex 4.0 SDK and currently we are not integrating with any Server side layer so we will leave that option as None/Other. Click on Finish at this point to create your Flex Project. This will create a main application file called MyFirstFB4App.mxml as shown below. We will come back to our coding a little later but first we must familiarize ourselves with the Flash Builder IDE. Let us first look at the Package Explorer to understand the files that have been created for the Flex Project. The screenshot is shown below: It consists of the main source file MyFirstFB4App.mxml. This is the main application file or in other words the bootstrap. All your source files (MXML and ActionScript code along with assets like images, and others should go under the src folder. They can optionally be placed in packages too. The Flex 4.0 framework consists of several libraries that you compile your code against. You would end up using its framework code, components (visual and non-visual) and other classes. These classes are packaged in a library file with an extension .swc. A list of library files is shown above. You do not need to typically do anything with it. Optionally, you can also use 3rd party components written by other companies and developers that are not part of the Flex framework. These libraries are packages as .SWC files too and they can be placed in the libs folder as shown in the previous screenshot. The typical step is to write and compile your code—build your project. If your build is successful, the object code is generated in the bin-debug folder. When you deploy your application to a Web Server, you will need to pickup the contents from this folder. We will come to that a little later. The html-template folder contains some boiler-plate code that contains the container HTML into which your object code will be referenced. It is possible to customize this but for now, we will not discuss that. Double-click MyFirstFB4App.mxml file. This is our main application file. The code listing is given below: <?xml version="1.0" encoding="utf-8"?> <s:Application minWidth="1024" minHeight="768"> </s:Application> As discussed before, you will typically write one or more MXML files that will contain typically your visual components (although there can be non-visual components also). By visual components, we mean controls like button, combobox, list, tree, and others. It could also contain layout components and containers that help you layout your design as per the application screen design. To view what components, you can place on the main application canvas, select the Design View as shown below: Have a look at the lower half of the left pane. You will see the Components tab as shown below, which would address most needs of your Application Visual design. Click on the Controls tree node as shown below. You will see several controls that you can use and from which, we will use the Button control for this application. Simply select the Button control and drag it to the Design View Canvas as shown below: This will drop an instance of the Button control on the Design View as shown below: Select the Button to see its properties panel as shown below. Properties Panel is where you can set several attributes at design time for the control. In case the Properties panel is not visible, you can get to that by selecting Window → Properties from the main menu. In the Properties panel, we can change several key attributes. All controls can be uniquely identified and addressed in your code via the ID attribute. This is a unique name that you need to provide. Go ahead and give it some meaningful name. In our case, we name it btnSayHello. Next we can change the label so that instead of Button, it can display a message for example, Say Hello. Finally we want to wire some code such that if the button is clicked, we can do some action like display a Message Box saying Hello World. To do that, click the icon next to the On click edit field as shown below. It will provide you two options. Select the option for Generate Event Handler. This will generate the code and switch to the Source view. The code is listed below for your reference. <?xml version="1.0" encoding="utf-8"?> <s:Application minWidth="1024" minHeight="768"> <fx:Script> <![CDATA[ protected function btnSayHello_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub } ]]> </fx:Script> <s:Button x="17" y="14" label="Button" id="btnSayHello" click="btnSayHello_clickHandler(event)"/> </s:Application> There are few things to note here. As mentioned most of your application logic will be written in ActionScript and that is exactly what Flash Builder has generated for you. All such code is typically added inside a scripting block marked with the <fx:Script> tag. You can place your ActionScript methods over here that can be used by the rest of the application. When we clicked on Generate Event Handler, Flash Builder generated the Event Handler code. This code is in ActionScript and was appropriately placed inside the <fx:Script> block for us. If you look at the code, you can see that it has added a function that is invoked when the click event is fired on the button. The method is btnSayHello_clickHandler and if you notice it has an empty method that is, no implementation. Let us run the application now to see what it looks like. To run the application, click on the   Run icon in the main toolbar of Flash Builder. This will launch the web application as shown below. Clicking the Say Hello button will not do anything at this point since there is no code written inside the handler as we saw above. To display the MessageBox, we add the code shown below (Only the Script section is shown below): <fx:Script> <![CDATA[ import mx.controls.Alert; protected function btnSayHello_clickHandler(event:MouseEvent):void { Alert.show("Hello World"); } ]]> </fx:Script> We use one of the classes (called Alert) from the Flex framework. Like any other language, we need to specify which package we are using the class from so that the compiler can understand it. The Alert class belongs to the mx.controls package and it has a static method called show() which takes a single parameter of type String. This String parameter is the message to be displayed and in our case it is "Hello World". To run this, click Ctrl-S to save your file or File →  Save from the main menu. And click on Run icon in the main toolbar. This will launch the application and on clicking the SayHello button, you will see the Hello World Alert window as shown below.
Read more
  • 0
  • 0
  • 3150
Modal Close icon
Modal Close icon