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-moodle-online-communities
Packt
14 Apr 2014
9 min read
Save for later

Moodle for Online Communities

Packt
14 Apr 2014
9 min read
(For more resources related to this topic, see here.) Now that you're familiar with the ways to use Moodle for different types of courses, it is time to take a look at how groups of people can come together as an online community and use Moodle to achieve their goals. For example, individuals who have the same interests and want to discuss and share information in order to transfer knowledge can do so very easily in a Moodle course that has been set up for that purpose. There are many practical uses of Moodle for online communities. For example, members of an association or employees of a company can come together to achieve a goal and finish a task. In this case, Moodle provides a perfect place to interact, collaborate, and create a final project or achieve a task. Online communities can also be focused on learning and achievement, and Moodle can be a perfect vehicle for encouraging online communities to support each other to learn, take assessments, and display their certificates and badges. Moodle is also a good platform for a Massive Open Online Course (MOOC). In this article, we'll create flexible Moodle courses that are ideal for online communities and that can be modified easily to create opportunities to harness the power of individuals in many different locations to teach and learn new knowledge and skills. In this article, we'll show you the benefit of Moodle and how to use Moodle for the following online communities and purposes: Knowledge-transfer-focused communities Task-focused communities Communities focused on learning and achievement Moodle and online communities It is often easy to think of Moodle as a learning management system that is used primarily by organizations for their students or employees. The community tends to be well defined as it usually consists of students pursuing a common end, employees of a company, or members of an association or society. However, there are many informal groups and communities that come together because they share interests, the desire to gain knowledge and skills, the need to work together to accomplish tasks, and let people know that they've reached milestones and acquired marketable abilities. For example, an online community may form around the topic of climate change. The group, which may use social media to communicate with each other, would like to share information and get in touch with like-minded individuals. While it's true that they can connect via Facebook, Twitter, and other social media formats, they may lack a platform that gives a "one-stop shopping" solution. Moodle makes it easy to share documents, videos, maps, graphics, audio files, and presentations. It also allows the users to interact with each other via discussion forums. Because we can use but not control social networks, it's important to be mindful of security issues. For that reason, Moodle administrators may wish to consider ways to back up or duplicate key posts or insights within the Moodle installation that can be preserved and stored. In another example, individuals may come together to accomplish a specific task. For example, a group of volunteers may come together to organize a 5K run fundraiser for epilepsy awareness. For such a case, Moodle has an array of activities and resources that can make it possible to collaborate in the planning and publicity of the event and even in the creation of post event summary reports and press releases. Finally, let's consider a person who may wish to ensure that potential employers know the kinds of skills they possess. They can display the certificates they've earned by completing online courses as well as their badges, digital certificates, mentions in high achievers lists, and other gamified evidence of achievement. There are also the MOOCs, which bring together instructional materials, guided group discussions, and automated assessments. With its features and flexibility, Moodle is a perfect platform for MOOCs. Building a knowledge-based online community For our knowledge-based online community, let's consider a group of individuals who would like to know more about climate change and its impact. To build a knowledge-based online community, the following are the steps we need to perform: Choose a mobile-friendly theme. Customize the appearance of your site. Select resources and activities. Moodle makes it possible for people from all locations and affiliations to come together and share information in order to achieve a common objective. We will see how to do this in the following sections. Choosing the best theme for your knowledge-based Moodle online communities As many of the users in the community access Moodle using smartphones, tablets, laptops, and desktops, it is a good idea to select a theme that is responsive, which means that it will be automatically formatted in order to display properly on all devices. You can learn more about themes for Moodle, review them, find out about the developers, read comments, and then download them at https://moodle.org/plugins/browse.php?list=category&id=3. There are many good responsive themes, such as the popular Buckle theme and the Clean theme, that also allow you to customize them. These are the core and contributed themes, which is to say that they were created by developers and are either part of the Moodle installation or available for free download. If you have Moodle 2.5 or a later version installed, your installation of Moodle includes many responsive themes. If it does not, you will need to download and install a theme. In order to select an installed theme, perform the following steps: In the Site administration menu, click on the Appearance menu. Click on Themes. Click on Theme selector. Click on the Change theme button. Review all the themes. Click on the Use theme button next to the theme you want to choose and then click on Continue. Using the best settings for knowledge-based Moodle online communities There are a number of things you can do to customize the appearance of your site so that it is very functional for knowledge-transfer-based Moodle online communities. The following is a brief checklist of items: Select Topics format under the Course format section in the Course default settings window. By selecting topics, you'll be able to organize your content around subjects. Use the General section, which is included as the first topic in all courses. It has the News forum link. You can use this for announcements highlighting resources shared by the community. Include the name of the main contact along with his/her photograph and a brief biographical sketch in News forum. You'll create the sense that there is a real "go-to" person who is helping guide the endeavor. Incorporate social media to encourage sharing and dissemination of new information. Brief updates are very effective, so you may consider including a Twitter feed by adding your Twitter account as one of your social media sites. Even though your main topic of discussion may contain hundreds of subtopics that are of great interest, when you create your Moodle course, it's best to limit the number of subtopics to four or five. If you have too many choices, your users will be too scattered and will not have a chance to connect with each other. Think of your Moodle site as a meeting point. Do you want to have too many breakout sessions and rooms or do you want to have a main networking site? Think of how you would like to encourage users to mingle and interact. Selecting resources and activities for a knowledge-based Moodle online community The following are the items to include if you want to configure Moodle such that it is ideal for individuals who have come together to gain knowledge on a specific topic or problem: Resources: Be sure to include multiple types of files: documents, videos, audio files, and presentations. Activities: Include Quiz and other such activities that allow individuals to test their knowledge. Communication-focused activities: Set up a discussion forum to enable community members to post their thoughts and respond to each other. The key to creating an effective Moodle course for knowledge-transfer-based communities is to give the individual members a chance to post critical and useful information, no matter what the format or the size, and to accommodate social networks. Building a task-based online community Let's consider a group of individuals who are getting together to plan a fundraising event. They need to plan activities, develop materials, and prepare a final report. Moodle can make it fairly easy for people to work together to plan events, collaborate on the development of materials, and share information for a final report. Choosing the best theme for your task-based Moodle online communities If you're using volunteers or people who are using Moodle just for the tasks or completion of tasks, you may have quite a few Moodle "newbies". Since people will be unfamiliar with navigating Moodle and finding the places they need to go, you'll need a theme that is clear, attention-grabbing, and that includes easy-to-follow directions. There are a few themes that are ideal for collaborations and multiple functional groups. We highly recommend the Formal white theme because it is highly customizable from the Theme settings page. You can easily customize the background, text colors, logos, font size, font weight, block size, and more, enabling you to create a clear, friendly, and brand-recognizable site. Formal white is a standard theme, kept up to date, and can be used on many versions of Moodle. You can learn more about the Formal white theme and download it by visiting http://hub.packtpub.com/wp-content/uploads/2014/04/Filetheme_formalwhite.png. In order to customize the appearance of your entire site, perform the following steps: In the Site administration menu, click on Appearance. Click on Themes. Click on Theme settings. Review all the themes settings. Enter the custom information in each box.
Read more
  • 0
  • 0
  • 3392

article-image-installing-drupal-7
Packt
24 Nov 2010
9 min read
Save for later

Installing Drupal 7

Packt
24 Nov 2010
9 min read
Drupal 7 First Look Learn the new features of Drupal 7, how they work and how they will impact you Get to grips with all of the new features in Drupal 7 Upgrade your Drupal 6 site, themes, and modules to Drupal 7 Explore the new Drupal 7 administration interface and map your Drupal 6 administration interface to the new Drupal 7 structure Complete coverage of the DBTNG database layer with usage examples and all API changes for both Themes and Modules         Read more about this book       (For more resources on Drupal, see here.) Drupal's installation process has always been very easy to use, and the Drupal 7 installation makes things even easier. Before beginning to install Drupal 7, you will need a web server running the Apache HTTPD web server. You can also use IIS on Microsoft Windows, but the Apache server is preferred and you will be able to obtain support from the community more easily if you use the Apache server. Want to easily install Apache onto a Microsoft Windows machine? Try XAMPP, which is published by Apache Friends. This package includes Apache, MySQL, and PHP with a standard Microsoft Windows installer. You can download XAMPP from http://www.apachefriends. org/en/xampp.html. Other options include WAMP (http://www. wampserver.com/en/) and MoWeS Portable (http://www. chsoftware.net/en/mowes/mowesportable/mowes.htm). Your server will also need PHP installed on it. Drupal requires at least PHP version 5.2.0. As of this writing, there are some hosts that still do not have PHP 5.2.0 or later installed on their shared hosting accounts, and Red Hat does not include PHP 5.2.0 or later in its default distribution. Check with your host or system administrator before installing Drupal to make sure that the correct version is available. In addition to the web server and PHP, you will also need a database. MySQL and PostgreSQL are the databases that are most frequently used with Drupal, and of the two, MySQL is much more widely used. That being said, you can use Drupal with many different databases and the new DBTNG database abstraction layer will make it easier to deploy to any database. If you are using MySQL, you will need version 5.0.15 or later installed. If you are using PostgreSQL, you will need PostgreSQL 8.3.0 or later. SQLite is also officially supported for use with Drupal and you will need version 3.4.2 or later. After you have a server set up with the proper software, you can download Drupal and begin the installation process. Obtaining Drupal If you have used previous versions of Drupal, the process for downloading Drupal is the same as always. If you are new to Drupal, you will use the following process: Go to the Drupal project page on Drupal.org: http://drupal.org/project/ drupal. Find the latest official release of Drupal 7 and click on the Download link. The release will be named 7.0 or similar. Your browser will ask whether you want to download or Open the file. Make sure to download it to your computer. The file you downloaded is a .tar.gz file, which is a compressed archive similar to a .zip file. You will need to extract the files from this archive onto your computer. If your computer doesn't already have a program that can open .tar.gz files, try 7-Zip, an open source application that easily handles these files. You can download 7-Zip from http://www.7-zip.org. After you have extracted the files, you will need to copy them to your web server's document root. You are now ready to start the installation process. Simply navigate to http://yoursite.com/install.php. Let's step through the installation process in detail now. Selecting an installation profile The first step in the installation process is selecting an installation profile. Drupal prompts you with a screen asking for which installation profile you want to use during the installation: By default, Drupal comes with two installation profiles, the Standard profile and the Minimal profile. Custom distributions may come with additional profiles. Minimal profile The Minimal profile installs a basic configuration of Drupal with only the required functionality enabled. This profile is even more minimal than the base Drupal 6 installation. This profile should be used if you are very familiar with setting up Drupal and don't want some of the additional features activated in the Standard profile. Standard profile The Standard Drupal profile installs and activates several commonly-used features to make your Drupal site more useful immediately. These additional features include: Search form installed on the left sidebar. Powered by Drupal block enabled in the footer. A basic page content type is automatically created to store static content on your site. An article content type is automatically created to store time-specific content. The article content type replaces the story content type from Drupal 6. Both content types are set up with RDF capabilities. User profiles have pictures enabled by default. Profile pictures can have a maximum size of 1024x1024 pixels and be up to 800 KB when they are uploaded. They will be displayed using the thumbnail image style. A taxonomy called Tags is created to allow easy categorization of content on your site. The article content type is enhanced by adding an image field, which allows PNG, GIF, and JPG files to be attached to the article. An administrator role is created that has all permissions activated for it. As new modules are activated, the administrator role will automatically be updated with the permissions for the new module. The Seven theme is activated for the administration section of the site. In most cases, you will want to start with the Standard installation profile, especially if you are setting up an entirely new site or if you are new to Drupal. Language selection The next step in the installation is choosing the language with which you want to install Drupal. By default, Drupal only includes an English installer. If you want to want to install Drupal in another language, you will need to download a translation from Drupal.org. A complete list of translations is available at http://drupal.org/ project/translations. After you download the translation you want to use, you will need to unpack the translation and copy it to your document folder. The process to unpack and copy the files is similar to the process we used when we unpacked and copied the core Drupal files to your server. For now, we will continue with the English installation. Requirements check Drupal will now check the requirements of your server to ensure that it meets the minimum requirements to run Drupal and to ensure that everything is ready for the installation to proceed. The requirements check will appear similar to the following: If Drupal does discover any problems, it will give you information about how to correct the problem. In our case, it looks like we forgot to set up our settings file. The settings file tells Drupal which database to connect to as well as the connection information. To create a settings file, navigate to your document root and then navigate to the sites/default folder. Copy the default.settings.php file to settings.php. You do not need to change any of the information within the file. After you have corrected any problems, click on the proceed with the installation link. Drupal will re-evaluate the requirements and let you know if anything else needs to be changed. This screen has been enhanced in Drupal 7 to provide much more information about your current server settings. Database configuration The next step in installing Drupal is configuring the database where Drupal will store the content and configuration information for your site. The functionality of this screen has also been enhanced in Drupal 7. The key difference is that Drupal 7 will automatically check which types of databases are available to you based on your server setup. Then, it will only allow you to select a database which will work. If you want to run Drupal using a different database server than your web server, you can use the ADVANCED OPTIONS link to configure the database server and port. You can also use ADVANCED OPTIONS if you are setting up multiple sites within a single database. For a Standard installation, enter the name of your database as well as the username and password for the database. This functionality remains the same as in Drupal 6. You will need to create a database outside of the Drupal installation. The actual steps for creating a new database vary depending on your website host. Many hosts have installed phpMyAdmin, which allows you to manage your databases with an easy-to-use web-based interface. If you use phpMyAdmin to create your database, you will need to log in to phpMyAdmin and create a database. You can create a new database from the home page, which should appear similar to the following screenshot depending on the version of phpMyAdmin you are using: You can create a new user for the database in the Privileges tab. After you have entered your database settings, click on the Save and continue button. Drupal will now configure the database and set up your site. As the installation proceeds, Drupal will display its progress. The installation may take several minutes to complete. In the unlikely event that you have problems during the installation, try emptying the database, increasing the amount of memory available to Drupal, and increasing the maximum execution time for a PHP script. You can increase the available memory and execution time in your php.ini file. The relevant sections in php.ini to control memory and execution time are shown in the following screenshot:
Read more
  • 0
  • 0
  • 3392

article-image-configuring-clusters-glassfish
Packt
29 Dec 2009
7 min read
Save for later

Configuring Clusters in GlassFish

Packt
29 Dec 2009
7 min read
Configuring clusters for GlassFish In order to deliver the required performance, throughput, and reliability, a production environment typically needs to host enterprise applications using multiple running application server instances. In order to easily configure and maintain these server instances, most application server products, including GlassFish, allow these server instances to be grouped into a cluster and administered together. In this section, we first review the core concepts of the GlassFish cluster, and then show you how to configure and manage clusters. Understanding GlassFish clusters A GlassFish cluster is a logical entity that groups multiple GlassFish Server instances. The server instances within a cluster can run on different physical machines or on the same machine. The cluster is administered by the Domain Administration Server (DAS). The server instances in a cluster share the same configuration, and they host all applications and resources deployed to the cluster. The main benefit of a cluster is that it significantly simplifies the administration of server instances. Instead of configuring these server instances and deploying applications to them individually, a cluster provides a one-stop administration facility to enforce the homogeneity of server instances. Besides, a cluster provides very good support for horizontal scalability. For example, if the production environment no longer has sufficient processing power, we can dynamically create a GlassFish Server instance and add it to the existing cluster without extensive reconfiguration. Finally, with the help of a load balancer and appropriate HA configuration, a cluster can be made resilient to server instance issues. We will focus on the clustering aspect of GlassFish in this section. Load balancers and HA will be discussed later in this article. The following figure illustrates the main components of a cluster from the administration perspective. The components illustrated in the figure are described as follows: The Domain Administration Server (DAS): DAS is a special server instance responsible for administration of a domain. All administrative operations are routed to DAS. Upon receiving administrative requests, DAS is responsible for sending the request to an individual server instance, or broadcasting it to all the server instances in a cluster. DAS can administer server instances running on remote hosts as well. Node agent: A node agent is a light-weight process running on the physical server that hosts GlassFish Server instances. The node agent is responsible for managing the life cycle of these server instances. It can perform the following tasks: Start, stop, restart, create, and delete server instances Provide a view of the log files of failed server instance If the node agent crashes, it does not affect the server instances and user applications that are currently running. However, a failed node agent can no longer manage and monitor those server instances. Server instance: With the exception of DAS, all the other server instances must be created with a reference to a node agent. A server instance can be stand-alone, or it can belong to a cluster. A stand-alone instance maintains and uses its own configuration, while a clustered instance inherits majority of the configuration information from the cluster. In our experience, stand-alone server instances are rarely used. Even if you only need one server instance to host applications, we recommend that you define a cluster with only one instance. This approach always allows the server to be potentially scaled out by adding additional server instances to the cluster. The overhead of clustered instance is completely negligible. The central repository and repository cache: The central repository is maintained by DAS. The central repository contains the server instance configuration data, and the applications deployed to the GlassFish domain. Each server instance and cluster synchronizes the central repository to its local repository cache. Keep in mind that the repository cache is a subset of the central repository, because the server instance and cluster only synchronize the information pertinent to itself. The local repository cache makes it possible to keep stand-alone and clustered server instances running while DAS is shut down. In fact, many organizations indeed shut down DAS in production environment, and they only start up the DAS when there is a new deployment of applications or resources. Without the DAS running, the GlassFish configuration cannot be changed using common administrative tasks. A node agent is associated with a particular domain when it is created, and it can service only a single domain. If a physical machine hosts server instances that belong to multiple domains, it must run multiple node agents, one for each domain. DAS only needs the node agent to perform administrative operations on the server instances. The synchronization between DAS and server instances takes place directly through the JMX API remote connector. The server instance or node agent synchronizes its state with the central repository in the following cases: completely at instance or node agent creation and start-up time, and incrementally as configuration changes are made to the central repository. Now let's dive into the process of configuring a GlassFish cluster. Configuring clusters In this section, we discuss the necessary steps to configure a GlassFish cluster, and along the way we will discuss more features of the GlassFish cluster. GlassFish clusters can be created on most operating system and hardware platforms. The noticeable exceptions are Microsoft Windows running the 64-bit JDK software, and Mac OSX. Obtaining cluster support The very first thing we need to do in order to configure a cluster is to make sure that the GlassFish Server we are working with has cluster support. Earlier, we introduced the concept of the usage profile of GlassFish. As it turned out, clustering support is available in the cluster and enterprise profiles, and not in the developer profile by default. However, even if we originally installed GlassFish in the developer profile, we can easily upgrade the GlassFish Server to enable clustering support. To do this, complete the following steps: Log on to the GlassFish Admin Console. Click the Application Server node in the navigation pane. Click the General tab in the main content pane. Click Add Cluster Support, as shown in the following screenshot. Click OK to confirm the choice. Restart the GlassFish Server. Once GlassFish restarts, we can log on to the Admin Console. We can confirm the cluster support by verifying the new Admin Console, as shown in the following screenshot. As we can see, in the navigation panel, the previous Application Server node is replaced by the Domain node. If we click this node in the navigation panel, we will see just a few configuration options, such as managing the administrator password. Most of the other management options, such as JVM settings are no longer there in the Admin Console. The reason is that those features, such as JVM settings are applied to individual server instances. Therefore, these properties are now associated with the server instances in the cluster profile. For a GlassFish Server that is upgraded from the developer profile, the original server instance now becomes the DAS instance and GlassFish treats the DAS as a stand-alone server instance. When we log on to the Admin Console, this server is listed under the Stand-Alone Instances node. Once we have enabled clusters for GlassFish, we can start creating clusters. As all server instances are managed through node agents, the next step in creating a cluster is to create and start the node agents.
Read more
  • 0
  • 0
  • 3391

article-image-moodle-19-theme-design-customizing-header-and-footer-part-2
Packt
23 Apr 2010
6 min read
Save for later

Moodle 1.9 Theme Design: Customizing the Header and Footer (Part 2)

Packt
23 Apr 2010
6 min read
Customizing the footer Obviously, the second thing that we are going to do after we have made changes to our Moodle header file is to carry on and change the footer.html file. The following tasks will be slightly easier than changing the header logo and title text within our Moodle site, as there is much less code and subsequently much less to change. Removing the Moodle logo The first thing that we will notice about the footer in Moodle is that it has the Moodle logo on the front page of your Moodle site and a Home button on all other pages. In addition to this, there is the login info text that shows who is logged in and a link to log out. More often than not Moodle themers will want to remove the Moodle logo so that they can give their Moodle site its own branding. So let's get stuck in with the next exercise, but don't forget that this logo credits the Moodle community. Time for action – deleting the Moodle logo Navigate to your mytheme directory and right-click on the footer.html file and choose Open With | WordPad. Find the following two lines of code: echo $loggedinas;echo $homelink; Comment out the second line using a PHP comment: echo $loggedinas;/*echo $homelink; */ Save the footer.html file and refresh your browser window. You should now see the footer without the Moodle logo. What just happened? In this exercise, we learned which parts of the PHP code in the footer.html file control where the Moodle logo appears in the Moodle footer. We also learned how to comment out the PHP code that controls the rendering of the Moodle logo so that it does not appear. You could try to put the Moodle logo back if you want. Removing the login info text and link Now that we have removed the Moodle logo, which of course is completely up to you, you might also want to remove the login info link. This link is used exactly like the one in the top right-hand corner of your Moodle site, insofar as it acts as a place where you can log in and log out and provide details of who you logged in as. The only thing to consider here is that if you decide to remove the login info link from the header.html file and also remove it from the footer, you will have no easy way of logging in or out of Moodle. So it is always wise to leave it either in the header or the footer. You might also consider the advantages of having this here as some Moodle pages such as large courses are very long. So, once the user has scrolled way down the page, he/she has a place to log out if needed. The following task is very simple and will require you to go through similar steps as the"deleting the logo" exercise. The only difference is that you will comment out a different line of code. Time for action – deleting the login info text Navigate to your mytheme directory and right-click on the footer.html file and choose Open With | WordPad (or an editor of your choice). Find the following two lines of code: echo $loggedinas;echo $homelink; Comment out the first line by using a PHP comment as shown below: /* echo $loggedinas; */ echo $homelink; Save the footer.html file and refresh your browser window. You will see the footer without the Moodle logo or the login info link. What just happened? In this task, we learned about those parts of the PHP code in the footer.html that control whether the Moodle login info text appears in the Moodle footer similar to the Moodle logo in the previous exercise. We also learned how to comment out the code that controls the rendering of the login info text so that it does not appear. Have a go hero – adding your own copyright or footer text The next thing that we are going to do in this article is to add some custom footer text where the Moodle logo and the login info text were before we removed them. It's completely up to you what to add in the next exercises. If you would like to just add some text to the footer then please do. However, as part of the following tasks we are going to add some copyright text and format it using some very basic HTML. Time for action – adding your own footer text Navigate to your mytheme directory and right-click on the footer.html file and choose Open With | WordPad. At the very top of the file, paste the following text or choose your own footer text to include: My School © 2009/10 All rights reserved. Save the footer.html and refresh your browser. You will see that your footer text is at the bottom of the page on the right-hand side. However, this text is aligned to the left as all text in a browser would be. Open the footer.html file again (if it isn't open already) and wrap the following code around the footer text that you have just added: <div align="right">My School &copy; 2009/10 All rights reserved</div> Save your footer.html file and refresh your browser. You will see that the text is now aligned to the right. What just happened? We just added some very basic footer text to our footer.html file, saved it, and viewed it in our web browser. We have demonstrated here that it is very easy to add our own text to the footer.html file. We have also added some basic HTML formatting to move the text from the left to the right-hand side of the footer. There are other ways to do so, which involve the use of CSS. For instance, we could have given the <div> tag a CSS class and used a CSS selector to align the text to the right. Have a go hero – adding your own footer logo Now try to see if you can edit the footer.html and add the same logo as you have in the header.html in to the footer. Remember that you can put the logo code anywhere outside of a PHP code block. So try to copy the header logo code and paste it into the footer.html. Finally, based on what we have learned, try to align the logo to the right as we did with the footer text.
Read more
  • 0
  • 0
  • 3390

article-image-adding-image-content-joomla
Packt
23 Feb 2010
6 min read
Save for later

Adding Image Content in Joomla!

Packt
23 Feb 2010
6 min read
Images and why we use them in websites Research suggests that images enhance learning by illustrating the concepts visually and by providing visual memory cues to the viewer. We have been using images to describe, tell stories, and record history since our human evolution. I have been in a few situations where, if a language barrier between me and the other party exists, we have resorted to a pencil and napkin in order to communicate effectively. Pictures can convey a message, which might take many thousands of words to describe. This non-textual communication and the visual emotions that the use of images can generate mean they are the perfect medium to complement or replace the text in our web pages: The previous image could easily take a thousand words to describe, which would look uninteresting to the reader and take up valuable space on our web pages. Instead the picture only utilizes a fraction of the space that our description would use and tells a story in itself. Not only do images describe a story, a moment in time, or a fantasy situation; they can provide a visual stimulus, which portrays a style or theme and sets a mood for the viewer. Many Joomla! Templates now contain a high percentage of graphical images in order to produce interesting designs and effects, such as this commercial example from http://www.yootheme.com: Many templates now utilize rounded edges for the graphics, or faded effects, and some create a 3D type effect on our two-dimensional computer screens. This is achieved by using shading and image layering effects. Others use images to create interesting navigation effects which could not be achieved without using these. Besides the design, navigation, and branding effects that images help provide, inside our content and modules, we use images to advertise and communicate to our site visitors. One important trick as web developers is to make sure our images are as optimized as they can be before asking our viewers to load them into their web browsers. This ensures a pleasant user experience because if a site is slow to load, or images are missing, these can be a big turn-off to your site visitors. Image formats and which ones to use Images can often make up 50 percent of a Joomla! website; sometimes even more. These images that get loaded into the browser can be part of your template design, or site images we have loaded into our modules and articles. Choosing an appropriate format for this image content will help optimize the loading times of your web pages, which is one of the most important considerations when building a multimedia rich website: There are a few simple rules we can use in order to choose an appropriate image format. The most important criterion for the final file is the size. The previous image is exported using Adobe Fireworks on a Mac computer. External image editors such as the GNU Image Manipulation Program (GIMP) are good open source solutions for manipulating and optimizing images for the web. GIMP can be downloaded by visiting http://www.gimp.org. With each image requiring loading by the user's browser, page-loading times can be easily affected with the quality and quantity of images you use in your web pages. This in turn results in end user frustration (especially on dial-up Internet connections) and loss of site traffic. Digital images Before we proceed further into file sizes and file types, it is important to mention a note about digital images. Because all of our web page images are stored or viewed on a computer device, they are in a digital format (an electronic file stored using zeros and ones). A digital image is built up of tiny elements called pixels. Pixels are the building blocks of all digital images and are small adjoining squares in a matrix across the length and width of your image. Pixels are so small that you cannot easily see them when the image is viewed on your computer screen: Each pixel is an element containing a single solid color, and when put together all of these tiny dots make up your final image. Usually, more pixels per area make up a higher quality image, but there is a poin t when viewed with the human eye on electronic devices that you cannot actually see the extra detail that the additional pixel's bring to the image: The physical dimensions of a digital image are measured in pixels and all digital images have what is called an image resolution (the image height and width dimensions in pixels). It is possible to save your digital images in numerous formats and compressions in order to optimize the file quality and size. Image editing programs, such as Adobe Fireworks, are specifically designed with web optimization and export options: Lossy and lossless data compression Data compression is an important part of our digital world. File compression is useful because it helps in reducing the consumption of expensive resources such as transmission bandwidth and computer hard disk space. Almost all digital images that we use on the web have been resized or compressed to some degree. When editing or saving files in popular software editing programs, many options are provided to help optimize digital images. Lossy and lossless compression are two terms that describe the compression type of a file, and whether or not the file retains all of the original data once compression and then decompression of that file has taken place. The preferred formats for digital web images (such as JPEG and GIF) all fall into one of the following compression types: LossyA lossy data compression is one where the compression attempts to eliminate redundant or unnecessary file information. Generally, once a file has been compressed, the information that was lost during compression cannot be recovered again. Hence, it is a degradable compression type, and as the file is compressed and decompressed each time, the quality of the file will suffer from generation loss.JPEG and MP3 files are good examples of formats that use lossy compression. LosslessLossless file compression makes use of data compression that retains every single bit of data that was in the original file before compression.Lossless compression is often used when an identical representation of the original data is required once a file has been compressed and then decompressed again. As an example, it is used for the popular ZIP file format. Image formats such as PNG and GIF fall into the lossless compression type. For now, it is not so important to go into any more detail on these compression types, but the following image formats fall into both of these compression categories. It is possible to optimize your website images by choosing the correct format to save and present them to your site users.
Read more
  • 0
  • 0
  • 3389

article-image-grails-object-relational-mapping-gorm
Packt
08 Jun 2010
5 min read
Save for later

The Grails Object Relational Mapping (GORM)

Packt
08 Jun 2010
5 min read
(For more resources on Groovy DSL, see here.) The Grails framework is an open source web application framework built for the Groovy language. Grails not only leverages Hibernate under the covers as its persistence layer, but also implements its own Object Relational Mapping layer for Groovy, known as GORM. With GORM, we can take a POGO class and decorate it with DSL-like settings in order to control how it is persisted. Grails programmers use GORM classes as a mini language for describing the persistent objects in their application. In this section, we will do a whistle-stop tour of the features of Grails. This won't be a tutorial on building Grails applications, as the subject is too big to be covered here. Our main focus will be on how GORM implements its Object model in the domain classes. Grails quick start Before we proceed, we need to install Grails and get a basic app installation up and running. The Grails' download and installation instructions can be found at http://www.grails.org/Installation. Once it has been installed, and with the Grails binaries in your path, navigate to a workspace directory and issue the following command: grails create-app GroovyDSL This builds a Grails application tree called GroovyDSL under your current workspace directory. If we now navigate to this directory, we can launch the Grails app. By default, the app will display a welcome page at http://localhost:8080/GroovyDSL/. cd GroovyDSLgrails run-app The grails-app directory The GroovyDSL application that we built earlier has a grails-app subdirectory, which is where the application source files for our application will reside. We only need to concern ourselves with the grails-app/domain directory for this discussion, but it's worth understanding a little about some of the other important directories. grails-app/conf: This is where the Grails configuration files reside. grails-app/controllers: Grails uses a Model View Controller (MVC) architecture. The controller directory will contain the Groovy controller code for our UIs. grails-app/domain: This is where Grails stores the GORM model classes of the application. grails-app/view: This is where the Groovy Server Pages (GSPs), the Grails equivalent to JSPs are stored. Grails has a number of shortcut commands that allow us to quickly build out the objects for our model. As we progress through this section, we will take a look back at these directories to see what files have been generated in these directories for us. In this section, we will be taking a whistle-stop tour through GORM. You might like to dig deeper into both GORM and Grails yourself. You can find further online documentation for GORM at http://www.grails.org/GORM. DataSource configuration Out of the box, Grails is configured to use an embedded HSQL in-memory database. This is useful as a means of getting up and running quickly, and all of the example code will work perfectly well with the default configuration. Having an in-memory database is helpful for testing because we always start with a clean slate. However, for the purpose of this section, it's also useful for us to have a proper database instance to peek into, in order to see how GORM maps Groovy objects into tables. We will configure our Grails application to persist in a MySQL database instance. Grails allows us to have separate configuration environments for development, testing, and production. We will configure our development environment to point to a MySQL instance, but we can leave the production and testing environments as they are. First of all we need to create a database, by using the mysqladmin command. This command will create a database called groovydsl, which is owned by the MySQL root user. mysqladmin -u root create groovydsl Database configuration in Grails is done by editing the DataSource.groovy source file in grails-app/conf. We are interested in the environments section of this file. environments { development { dataSource { dbCreate = "create-drop" url = "jdbc:mysql://localhost/groovydsl" driverClassName = "com.mysql.jdbc.Driver" username = "root" password = "" } } test { dataSource { dbCreate = "create-drop" url = "jdbc:hsqldb:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:hsqldb:mem:testDb" } }} The first interesting thing to note is that this is a mini Groovy DSL for describing data sources. In the previous version, we have edited the development dataSource entry to point to the MySQL groovydsl database that we created. In early versions of Grails, there were three separate DataSource files that need to be configured for each environment, for example, DevelopmentDataSource.groovy. The equivalent DevelopmentDataSource.groovy file would be as follows: class DevelopmentDataSource { boolean pooling = true String dbCreate = "create-drop" String url = " jdbc:mysql://localhost/groovydsl " String driverClassName = "com.mysql.jdbc.Driver" String username = "root" String password = ""} The dbCreate field tells GORM what it should do with tables in the database, on startup. Setting this to create-drop will tell GORM to drop a table if it exists already, and create a new table, each time it runs. This will keep the database tables in sync with our GORM objects. You can also set dbCreate to update or create. DataSource.groovy is a handy little DSL for configuring the GORM database connections. Grails uses a utility class—groovu.utl. ConfigSlurper—for this DSL. The ConfigSlurper class allows us to easily parse a structured configuration file and convert it into a java.util.Properties object if we wish. Alternatively, we can navigate the ConfigObject returned by using dot notation. We can use the ConfigSlurper to open and navigate DataSource.groovy as shown in the next code snippet. ConfigSlurper has a built-in ability to partition the configuration by environment. If we construct the ConfigSlurper for a particular environment, it will only load the settings appropriate to that environment. def development = new ConfigSlurper("development").parse(newFile('DataSource.groovy').toURL())def production = new ConfigSlurper("production").parse(newFile('DataSource.groovy').toURL())assert development.dataSource.dbCreate == "create-drop"assert production.dataSource.dbCreate == "update"def props = development.toProperties()assert props["dataSource.dbCreate"] == "create-drop"
Read more
  • 0
  • 0
  • 3389
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-integration-system-center-operations-manager-2012-sp1
Packt
17 May 2013
9 min read
Save for later

Integration with System Center Operations Manager 2012 SP1

Packt
17 May 2013
9 min read
(For more resources related to this topic, see here.) This article provides tips and techniques to allow administrators to integrate Operations Manager 2012 with Virtual Machine Manager 2012 to monitor the health and performance of virtual machine hosts and their virtual machines, as well as to use the Operations Manager reporting functionality. In a hybrid hypervisor environment (for example, Hyper-V, VMware), using Operations Manager management packs ( MPs ) (for example, Veeam MP), you can monitor the Hyper-V hosts and the VMware hosts, which allow you to use only the System Center Console to manage and monitor the hybrid hypervisor environment. You can also monitor the health and availability of the VMM infrastructure, management, database, and library servers. The following screenshot will show you the diagram views of the virtualized environment through the Operations Manager: Installing System Center Operations Manager 2012 SP1 This recipe will guide you through the process of installing a System Center Operations Manager for the integration with VMM. Operations Manager has an integrated product and company knowledge for proactive tuning. It also allows the user to compute the OS, applications, services, and out-of-the-box network monitoring, reporting, and many more features extensibility through management packs, thus providing a cross-platform visibility. The deployment used on this recipe assumes a small environment with all components being installed on the same server. For datacenters and enterprise deployments, it is recommended to distribute the features and services across multiple servers to allow for scalability. For a complete design reference and complex implementation of SCOM 2012, follow up the Microsoft Operations Manager deployment guide available at http://go.microsoft.com/fwlink/?LinkId=246682. When planning, use Operations Guide for System Center 2012—Operations Manager (http://go.microsoft.com/fwlink/p/?LinkID=207751) to determine the hardware requirements. Getting ready Before starting, check out the system requirements and design planning for System Center Operations Manager 2012 SP1 at http://technet.microsoft.com/en-us/library/jj656654.aspx My recommendation is to deploy on a Windows Server 2012 and the SQL Server 2012 SP1 version. How to do it... Carry out the following steps to install Operations Manager 2012 SP1: Browse to the SCOM installation folder and click on Setup. Click on Install. On the Select the features to install page, select the components that apply to your environment, and then click on Next as shown in the following screenshot: The recommendation is to have a dedicated server, but it all depends on the size of the deployment. You can select all of the components to be installed on the same server for a small deployment. Type in the location where you'd install Operations Manager 2012 SP1, or accept the default location and click on Next. The installation will check if your system has passed all of the requirements. A screen showing the issues will be displayed if any of the requirements are not met, and you will be asked to fix and verify it again before continuing with the installation, as shown in the following screenshot: If all of the prerequisites are met, click on Next to proceed with the setup. On the Specify an installation option page, if this is the first Operations Manager, select the Create the first Management Server in a new management group option and provide a value in the Management group name field. Otherwise, select the Add a management server to an existing management group option as shown in the following screenshot: Click on Next to continue, accept the EULA, and click on Next. On the Configure the operational database page, type the server and instance name of the server and the SQL Server port number. It is recommended to keep the default values in the Database name, Database size (MB), Data file folder, and Log file folder boxes. Click on Next. The installation account needs DB owner rights on the database. On the SQL Server instance for Reporting Services page, select the instance where you want to host the Reporting Services (SSRS). Make sure the SQL Server has the SQL Server Full-Text Search and Analysis server component installed. On the Configure Operations Manager accounts page, provide the domain account credentials (for example, labsvc-scom) for the Operations Manager services. You can use a single domain account. For account requirements, see the Microsoft Operations Manager deployment guide at http://go.microsoft.com/fwlink/?LinkId=246682. On the Help improve System Center 2012 – Operations Manager page, select the desired options and click on Next. On the Installation Summary page, review the options and click on Install, and then on click on Close. The Operations Manager console will open. How it works... When deploying SCOM 2012, it is important to consider the placement of the components. Work on the SCOM design before implementing it. See the OpsMgr 2012 Design Guide available at http://blogs.technet.com/b/momteam/archive/2012/04/13/ opsmgr-2012-design-guide.aspx. On the Configure Operational Database page, if you are installing the first management server, a new operational database will be created. If you are installing additional management servers, an existing database will be used. On the SQL Server instance for Reporting Services page, make sure you have previously configured the Reporting Services at SQL setup using the Reporting Services Configuration Manager tool, and that the SQL Server Agent is running. During the OpsMgr setup, you will be required to provide the Management Server Action Account credentials and the System Center Configuration service and System Center Data Access service account credentials too. The recommendation is to use a domain account so that you can use the same account for both the services. The setup will automatically assign the local computer Administrators group to the Operations Manager administrator's role. The single-server scenario combines all roles onto a single instance and supports the following services: monitoring and alerting, reporting, audit collection, agentless-exception management, and data. If you are planning to monitor the network, it is recommended to move the SQL Server tempdb database to a separate disk that has multiple spindles. There's more... To confirm the health of the management server, carry out the following steps: In the OpsMgr console, click on the Administration workspace. In Device Management, select Management Servers to confirm that the installed server has a green check mark in the Health State column. See also The Deploying System Center 2012 – Operations Manager article available at http://technet.microsoft.com/en-us/library/hh278852.aspx Installing management packs After installing Operations Manager, you need to install some management packs and agents on the Hyper-V servers and on the VMM server. This recipe will guide you through the installation, but first make sure you have installed the Operations Manager Operations console on the VMM management server. You need to import the following management packs for the VMM 2012 SP1 integration: Windows Server operating system Windows Server 2008 operating system (Discovery) Internet Information Services 2003 Internet Information Services 7 Internet Information Services library SQL Server Core Library Getting ready Before you begin, make sure the correct version of PowerShell is installed, that is, PowerShell v2 for SC 2012 and PowerShell v3 for SC2012 SP1. How to do it... Carry out the following steps to install the required MPs in order to integrate with VMM 2012 SP1: In the OpsMgr console, click on the Administration workspace on the bottom-left pane. On the left pane, right-click on Management Packs and click on Import Management Packs. In the Import Management Packs wizard, click on Add, and then click on Add from catalog. In the Select Management Packs from Catalog dialog box, for each of the following management packs, repeat the steps 5 to 7: Windows Server operating system Windows Server 2008 operating system (Discovery) Internet Information Services 2003 Internet Information Services 7 Internet Information Services library SQL Server Core Library There are numerous management packs for Operations Manager. You can use this recipe to install other OpsMgr MPs from the catalog web service. You can also download the MPs from the Microsoft System Center Marketplace, which contains the MPs and documentation from Microsoft and some non-Microsoft companies. Save them to a shared folder and then import. See http://systemcenter.pinpoint. microsoft.com/en-US/home. In the Find field, type in the management pack to search in the online catalog and click on Search. The Management packs in the catalog list will show all of the packs that match the search criterion. To import, select the management pack, click on Select, and then click on Add as shown in the following screenshot: In the View section, you can refine the search by selecting, for example, to show only those management packs released within the last three months. The default view lists all of the management packs in the catalog. Click on OK after adding the required management packs. On the Select Management Packs page, the MPs will be listed with either a green icon, a yellow icon, or a red icon. The green icon indicates that the MP can be imported. The yellow information icon means that it is dependent on other MPs that are available in the catalog, and you can fix the dependency by clicking on Resolve. The red error icon indicates that it is dependent on other MPs, but the dependent MPs are not available in the catalog. Click on Import if all management packs have their icon statuses as green. On the Import Management Packs page, the progress for each management pack will be displayed. Click on Close when the process is finished. How it works... You can import the management packs available for Operations Manager using the following: The OpsMgr console: You can perform the following actions in the Management Packs menu of the Administration workspace: Import directly from Microsoft's online catalog Import from disk/share Download the management pack from the online catalog to import at a later time The Internet browser: You can download the management pack from the online catalog to import at a later time, or to install on an OpsMgr that is not connected to the Internet While using the OpsMgr console, verify whether all management packs show a green status. Any MP displaying the yellow information icon or the red error icon in the import list will not be imported. If there is no Internet connection on the OpsMgr, use an Internet browser to locate and download the management pack to a folder/share. Then copy the management pack to the OpsMgr server and use the option to import from disk/share. See also The Installing System Center Operations Manager 2012 SP1 recipe Visit Microsoft System Center Marketplace available at http://go.microsoft.com/fwlink/?LinkId=82105
Read more
  • 0
  • 0
  • 3388

article-image-jira-programming-workflows
Packt
01 Dec 2011
20 min read
Save for later

JIRA: Programming Workflows

Packt
01 Dec 2011
20 min read
(For more resources on this topic, see here.) Introduction Workflows are one standout feature which help users to transform JIRA into a user-friendly system. It helps users to define a lifecycle for the issues, depending on the issue type, the purpose for which they are using JIRA, and so on. As the Atlassian documentation says at http://confluence.atlassian.com/display/JIRA/Configuring+Workflow: A JIRA workflow is the set of steps and transitions an issue goes through during its lifecycle. Workflows typically represent business processes. JIRA uses Opensymphony's OSWorkflow which is highly configurable, and more importantly pluggable, to cater for the various requirements. JIRA uses three different plugin modules to add extra functionalities into its workflow, which we will see in detail through this chapter. To make things easier, JIRA ships with a default workflow. We can't modify the default workflow, but can copy it into a new workflow and amend it to suit our needs. Before we go into the development aspect of a workflow, it makes sense to understand the various components of a workflow. The two most important components of a JIRA workflow are Step and Transition. At any point of time, an Issue will be in a step. Each step in the workflow is linked to a workflow Status (http://confluence.atlassian.com/display/JIRA/Defining+%27Status%27+F ield+Values) and it is this status that you will see on the issue at every stage. A transition, on the other hand, is a link between two steps. It allows the user to move an issue from one step to another (which essentially moves the issue from one status to another). Few key points to remember or understand about a workflow: An issue can exist in only one step at any point in time A status can be mapped to only one step in the workflow A transition is always one-way. So if you need to go back to the previous step, you need a different transition A transition can optionally specify a screen to be presented to the user with the right fields on it OSWorkflow, and hence JIRA, provides us with the option of adding various elements into a workflow transition which can be summarized as follows: Conditions: A set of conditions that need to be satisfied before the user can actually see the workflow action (transition) on the issue Validators: A set of validators which can be used to validate the user input before moving to the destination step Post Functions: A set of actions which will be performed after the issue is successfully moved to the destination step These three elements give us the flexibility of handling the various use cases when an issue is moved from one status to another. JIRA ships with a few built-in conditions, validators, and post functions. There are plugins out there which also provide a wide variety of useful workflow elements. And if you still don't find the one you are looking for, JIRA lets us write them as plugins. We will see how to do it in the various recipes in this chapter. Hopefully, that gives you a fair idea about the various workflow elements. A lot more on JIRA workflows can be found in the JIRA documentation at http://confluence.atlassian.com/display/JIRA/Configuring+Workflow. Writing a workflow condition What are workflow conditions? They determine whether a workflow action is available or not. Considering the importance of a workflow in installations and how there is a need to restrict the actions either to a set of people, roles, and so on, or based on some criteria (for example, the field is not empty!), writing workflow conditions is inevitable. Workflow conditions are created with the help of the workflow-condition module. The following are the key attributes and elements supported. See http://confluence.atlassian.com/display/JIRADEV/Workflow+Plugin+Modules#WorkflowPluginModules-Conditions for more details. Attributes: Name Description key This should be unique within the plugin. class Class to provide contexts for rendered velocity templates. Must implement the com.atlassian.jira.plugin.workflow.WorkflowPluginConditionFactory interface. i18n-name-key The localization key for the human-readable name of the plugin module. name Human-readable name of the workflow condition. Elements: Name Description description Description of the workflow condition. condition-class Class to determine whether the user can see the workflow transition. Must implement com.opensymphony.workflow.Condition. Recommended to extend the com.atlassian.jira.workflow.condition.AbstractJiraCondition class. resource type="velocity" Velocity templates for the workflow condition views. Getting ready As usual, create a skeleton plugin. Create an eclipse project using the skeleton plugin and we are good to go! How to do it... In this recipe, let's assume we are going to develop a workflow condition that limits a transition only to the users belonging to a specific project role. The following are the steps to write our condition: Define the inputs needed to configure the workflow condition. We need to implement the WorkflowPluginFactory interface, which mainly exists to provide velocity parameters to the templates. It will be used to extract the input parameters that are used in defining the condition. To make it clear, the inputs here are not the inputs while performing the workflow action, but the inputs in defining the condition. The condition factory class, RoleConditionFactory in this case, extends the AbstractWorkflowPluginFactory, which implements the WorkflowPluginFactory interface. There are three abstract methods that we should implement, that is, getVelocityParamsForInput, getVelocityParamsForEdit, and getVelocityParamsForView. All of them, as the name suggests, are used for populating the velocity parameters for the different scenarios. In our example, we need to limit the workflow action to a certain project role, and so we need to select the project role while defining the condition. The three methods will be implemented as follows: private static final String ROLE_NAME = "role";private static final String ROLES = "roles";.......@Override  protected void getVelocityParamsForEdit(Map<String, Object>velocityParams, AbstractDescriptor descriptor) {    velocityParams.put(ROLE, getRole(descriptor));    velocityParams.put(ROLES, getProjectRoles());  }   @Override  protected void getVelocityParamsForInput(Map<String, Object> velocityParams) {    velocityParams.put(ROLES, getProjectRoles());  }   @Override  protected void getVelocityParamsForView(Map<String, Object> velocityParams, AbstractDescriptor descriptor) {    velocityParams.put(ROLE, getRole(descriptor));  } Let's look at the methods in detail: getVelocityParamsForInput: This method defines the velocity parameters for input scenario, that is, when the user initially configures the workflow. In our example, we need to display all the project roles so that the user can select one to define the condition. The method getProjectRoles merely returns all the project roles and the collection of roles is then put into the velocity parameters with the key ROLES. getVelocityParamsForView: This method defines the velocity parameters for the view scenario, that is, how the user sees the condition after it is configured. In our example, we have defined a role and so we should display it to the user after retrieving it back from the workflow descriptor. If you have noticed, the descriptor, which is an instance of AbstractDescriptor, is available as an argument in the method. All we need is to extract the role from the descriptor, which can be done as follows: private ProjectRole getRole(AbstractDescriptor descriptor){    if (!(descriptor instanceof ConditionDescriptor)) {      throw new IllegalArgumentException("Descriptor must be aConditionDescriptor.");    }      ConditionDescriptor functionDescriptor = (ConditionDescriptor)descriptor;     String role = (String) functionDescriptor.getArgs().get(ROLE);    if (role!=null && role.trim().length()>0)      return getProjectRole(role);    else       return null;  } Just check if the descriptor is a condition descriptor or not, and then extract the role as shown in the preceding snippet. getVelocityParamsForEdit: This method defines the velocity parameters for the edit scenario, that is, when the user modifies the existing condition. Here we need both the options and the selected value. Hence, we put both the project roles collection and the selected role on to the velocity parameters. The second step is to define the velocity templates for each of the three aforementioned scenarios: input, view, and edit. We can use the same template here for input and edit with a simple check to keep the old role selected for the edit scenario. Let us look at the templates: edit-roleCondition.vm: Displays all project roles and highlights the already-selected one in the edit mode. In the input mode, the same template is reused, but the selected role will be null and hence a null check is done: <tr bgcolor="#ffffff">    <td align="right" valign="top" bgcolor="#fffff0">        <span class="label">Project Role:</span>    </td>    <td bgcolor="#ffffff" nowrap>        <select name="role" id="role">        #foreach ($field in $roles)          <option value="${field.id}"            #if ($role && (${field.id}==${role.id}))                SELECTED            #end            >$field.name</option>        #end        </select>        <br><font size="1">Select the role in which the user should be present!</font>    </td></tr> view-roleCondition.vm: Displays the selected role: #if ($role)  User should have ${role.name} Role!#else  Role Not Defined#end The third step is to write the actual condition. The condition class should extend the AbstractJiraCondition class. Here we need to implement the passesCondition method. In our case, we retrieve the project from the issue, check if the user has the appropriate project role, and return true if the user does: public boolean passesCondition(Map transientVars, Map args,PropertySet ps) throws WorkflowException {    Issue issue = getIssue(transientVars);    User user = getCaller(transientVars, args);     project project = issue.getProjectObject();    String role = (String)args.get(ROLE);    Long roleId = new Long(role);     return projectRoleManager.isUserInProjectRole(user,projectRoleManager.getProjectRole(roleId), project);} The issue on which the condition is checked can be retrieved using the getIssue method implemented in the AbstractJiraCondition class. Similarly, the user can be retrieved using the getCaller method. In the preceding method, projectRoleManager is injected in the constructor, as we have seen before. We can see that the ROLE key is used to retrieve the project role ID from the args parameter in the passesCondition method. In order for the ROLE key to be available in the args map, we need to override the getDescriptorParams method in the condition factory class, RoleConditionFactory in this case. The getDescriptorParams method returns a map of sanitized parameters, which will be passed into workflow plugin instances from the values in an array form submitted by velocity, given a set of name:value parameters from the plugin configuration page (that is, the 'input-parameters' velocity template). In our case, the method is overridden as follows: public Map<String, String> getDescriptorParams(Map<String, Object>conditionParams) {    if (conditionParams != null &&conditionParams.containsKey(ROLE))        {            return EasyMap.build(ROLE,extractSingleParam(conditionParams, ROLE));        }        // Create a 'hard coded' parameter        return EasyMap.build();  } The method here builds a map of the key:value pair, where key is ROLE and the value is the role value entered in the input configuration page. The extractSingleParam method is implemented in the AbstractWorkflowPluginFactory class. The extractMultipleParams method can be used if there is more than one parameter to be extracted! All that is left now is to populate the atlassian-plugin.xml file with the aforementioned components. We use the workflow-condition module and it looks like the following block of code: <workflow-condition key="role-condition" name="Role BasedCondition"  class="com.jtricks.RoleConditionFactory">    <description>Role Based Workflow Condition</description>    <condition-class>com.jtricks.RoleCondition</condition-class>    <resource type="velocity" name="view"location="templates/com/jtricks/view-roleCondition.vm"/>    <resource type="velocity" name="input-parameters"location="templates/com/jtricks/edit-roleCondition.vm"/>    <resource type="velocity" name="edit-parameters" location="templates/com/jtricks/edit-roleCondition.vm"/></workflow-condition> Package the plugin and deploy it! How it works... After the plugin is deployed, we need to modify the workflow to include the condition. The following screenshot is how the condition looks when it is added initially. This, as you now know, is rendered using the input template: After the condition is added (that is, after selecting the Developers role), the view is rendered using the view template and looks as shown in the following screenshot: (Move the mouse over the image to enlarge.) If you try to edit it, the screen will be rendered using the edit template, as shown in the following screenshot: Note that the Developers role is already selected. After the workflow is configured, when the user goes to an issue, he/she will be presented with the transition only if he/she is a member of the project role where the issue belongs. It is while viewing the issue that the passesCondition method in the condition class is executed. Writing a workflow validator Workflow validators are specific validators that check whether some pre-defined constraints are satisfied or not while progressing on a workflow. The constraints are configured in the workflow and the user will get an error if some of them are not satisfied. A typical example would be to check if a particular field is present or not before the issue is moved to a different status. Workflow validators are created with the help of the workflow- validator module. The following are the key attributes and elements supported. Attributes: Name Description key This should be unique within the plugin. class Class to provide contexts for rendered velocity templates. Must implement the com.atlassian.jira.plugin.workflow.WorkflowPluginValidatorFactory interface. i18n-name-key The localization key for the human-readable name of the plugin module. name Human-readable name of the workflow validator. Elements: Name Description description Description of the workflow validator. validator-class Class which does the validation. Must implement com.opensymphony.workflow.Validator. resource type="velocity" Velocity templates for the workflow validator views. See http://confluence.atlassian.com/display/JIRADEV/Workflow+Plugin+Modules#WorkflowPluginModules-Validators for more details. Getting ready As usual, create a skeleton plugin. Create an eclipse project using the skeleton plugin and we are good to go! How to do it... Let us consider writing a validator that checks whether a particular field has a value entered on the issue or not! We can do this using the following steps: Define the inputs needed to configure the workflow validator: We need to implement the WorkflowPluginValidatorFactory interface, which mainly exists to provide velocity parameters to the templates. It will be used to extract the input parameters that are used in defining the validator. To make it clear, the inputs here are not the input while performing the workflow action, but the inputs in defining the validator. The validator factory class, FieldValidatorFactory in this case, extends the AbstractWorkflowPluginFactory interface and implements the WorkflowPluginValidatorFactory interface. Just like conditions, there are three abstract methods that we should implement. They are getVelocityParamsForInput, getVelocityParamsForEdit, and getVelocityParamsForView. All of them, as the names suggest, are used for populating the velocity parameters in different scenarios. In our example, we have a single input field, which is the name of a custom field. The three methods will be implemented as follows: @Overrideprotected void getVelocityParamsForEdit(Map velocityParams,AbstractDescriptor descriptor) {    velocityParams.put(FIELD_NAME, getFieldName(descriptor));  velocityParams.put(FIELDS, getCFFields());} @Overrideprotected void getVelocityParamsForInput(Map velocityParams) {    velocityParams.put(FIELDS, getCFFields());} @Overrideprotected void getVelocityParamsForView(Map velocityParams,AbstractDescriptor descriptor) {    velocityParams.put(FIELD_NAME, getFieldName(descriptor));} You may have noticed that the methods look quite similar to the ones in a workflow condition, except for the business logic! Let us look at the methods in detail: getVelocityParamsForInput: This method defines the velocity parameters for input scenario, that is, when the user initially configures the workflow. In our example, we need to display all the custom fields, so that the user can select one to use in the validator. The method getCFFields returns all the custom fields and the collection of fields is then put into the velocity parameters with the key fields. getVelocityParamsForView: This method defines the velocity parameters for the view scenario, that is, how the user sees the validator after it is configured. In our example, we have defined a field and so we should display it to the user after retrieving it back from the workflow descriptor. You may have noticed that the descriptor, which is an instance of AbstractDescriptor, is available as an argument in the method. All we need is to extract the field name from the descriptor, which can be done as follows: private String getFieldName(AbstractDescriptor descriptor){  if (!(descriptor instanceof ValidatorDescriptor)) {    throw new IllegalArgumentException('Descriptor must be aValidatorDescriptor.');  }    ValidatorDescriptor validatorDescriptor = (ValidatorDescriptor)descriptor;   String field = (String)validatorDescriptor.getArgs().get(FIELD_NAME);  if (field != null && field.trim().length() > 0)    return field;  else    return NOT_DEFINED;} Just check if the descriptor is a validator descriptor or not and then extract the field as shown in the preceding snippet. getVelocityParamsForEdit: This method defines the velocity parameters for the edit scenario, that is, when the user modifies the existing validator. Here we need both the options and the selected value. Hence we put both the custom fields' collection and the field name onto the velocity parameters. The second step is to define the velocity templates for each of the three aforementioned scenarios, namely, input, view, and edit. We can use the same template here for input and edit with a simple checking to keep the old field selected for the edit scenario. Let us look at the template: edit-fieldValidator.vm: Displays all custom fields and highlights the already selected one in edit mode. In input mode, the field variable will be null, and so nothing is pre-selected: <tr bgcolor="#ffffff">  <td align="right" valign="top" bgcolor="#fffff0">    <span class="label">Custom Fields :</span>  </td>  <td bgcolor="#ffffff" nowrap>    <select name="field" id="field">    #foreach ($cf in $fields)      <option value="$cf.name"        #if ($cf.name.equals($field)) SELECTED #end      >$cf.name</option>    #end    </select>    <br><font size="1">Select the Custom Field to be validated for NULL</font>  </td></tr> view-fieldValidator.vm: Displays the selected field: #if ($field)  Field '$field' is Required!#end The third step is to write the actual validator. The validator class should implement the Validator interface. All we need here is to implement the validate method. In our example, we retrieve the custom field value from the issue and throw an InvalidInputException if the value is null (empty): public void validate(Map transientVars, Map args, PropertySet ps)throws InvalidInputException, WorkflowException {    Issue issue = (Issue) transientVars.get("issue");    String field = (String) args.get(FIELD_NAME);      CustomField customField = customFieldManager.getCustomFieldObjectByName(field);     if (customField!=null){      //Check if the custom field value is NULL      if (issue.getCustomFieldValue(customField) == null){        throw new InvalidInputException("The field:"+field+" is             required!"); }    }  } The issue on which the validation is done can be retrieved from the transientVars map. customFieldManager is injected in the constructor as usual. All that is left now is to populate the atlassian-plugin.xml file with these components. We use the workflow-validator module, and it looks like the following block of code: <workflow-validator key="field-validator" name="Field Validator"  class="com.jtricks.FieldValidatorFactory">    <description>Field Not Empty Workflow Validator</description>     <validator-class>com.jtricks.FieldValidator</validator-class>     <resource type="velocity" name="view"location="templates/com/jtricks/view-fieldValidator.vm"/>    <resource type="velocity" name="input-parameters" location="templates/com/jtricks/edit-fieldValidator.vm"/>    <resource type="velocity" name="edit-parameters"location="templates/com/jtricks/edit-fieldValidator.vm"/></workflow-validator> Package the plugin and deploy it! Note that we have stored the role name instead of the ID in the workflow, unlike what we did in the workflow condition. However, it is safe to use the ID because administrators can rename the roles, which would then need changes in the workflows. How it works... After the plugin is deployed, we need to modify the workflow to include the validator. The following screenshot is how the validator looks when it is added initially. This, as you now know, is rendered using the input template: After the validator is added (after selecting the Test Number field), it is rendered using the view template and looks as follows: If you try to edit it, the screen will be rendered using the edit template, as shown in the following screenshot: Note that the Test Number field is already selected. After the workflow is configured, when the user goes to an issue and tries to progress it, the validator will check if the Test Number field has a value or not. It is at this point that the validate method in the FieldValidator class is executed. If the value is missing, you will see an error, as shown in the following screenshot:
Read more
  • 0
  • 0
  • 3380

article-image-hacking-toys-ifttt-and-spark
David Resseguie
31 Mar 2015
6 min read
Save for later

Hacking toys with IFTTT and Spark

David Resseguie
31 Mar 2015
6 min read
Open up even the simplest of toys and you’ll often be amazed at the number of interesting electronic components inside. This is especially true in many of the otherwise “throw away” toys found in fast food kids’ meals. I’ve tried to make it a habit of salvaging as many parts as possible from such toys so I can use them in future projects. (And I recommend you do the same!) But what if we could use the toy itself as a basis for a new project? In this post, we’ll look at one example of how we can Internet-enable a simple LED lantern toy using a wireless Spark Core device and the powerful IFTTT service. This particular LED lantern is operated by a standard on-off switch, and inside is a single LED, three coin batteries, and a simple switch mechanism for connecting and disconnecting power. Like many fast-food premiums, the lantern uses “tamper proof” triangular screws. If you don’t have the appropriate bit, you can usually make do with a small straight edge screwdriver. In addition to screws, some toys are also glued or sonic welded together, which makes it difficult to open without damaging the plastic beyond repair. Not shown in this photo is a small plastic piece that holds all the components in place. To programmatically control our lantern, we want to remove the batteries and run jumper cables to a pin on our microcontroller instead. Here is an exposed view after also removing the switch mechanism and attaching female-male jumper cables to the positive and negative leads of the LED. The next step is to hook our lantern up to the Spark Core. We choose the Spark Core for this project for two primary reasons. First, the Spark’s size is very conducive to toy hacking, especially for projects where you want to completely embed the electronics inside the finished product. Second, there is already a Spark channel on IFTTT that allows us to remotely trigger actions. More on that later! But before we go too far, let’s test our Spark setup to be sure we can power the LED. Run the jumper cable from the positive lead to pin D0 and the negative lead to GND. Now let’s write a simple Spark application that turns the LED on and off. Using Spark’s Web IDE, flash the following program onto your Spark Core. This will cause the LED to blink on and off in one second intervals. int led = D0; void setup() { pinMode(led, OUTPUT); } void loop() { digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); } But to really make our project useful, we need to hook it up to the Internet and respond to remote triggers for controlling the LED. IFTTT (pronounced like “gift” without the “g”) is a web-based service for connecting a variety of other online services and devices through “recipes”. An IFTT recipe is of the form “If [this] then [that]. The services that can be combined to fill in those blanks are called “channels”. IFTTT has dozens of channels to pick from, including email, SMS, Twitter, etc. But especially important to us: there is a Spark channel that allows Spark devices to serve as both triggers and actuators. For this project, we’ll set up our Spark as an actuator that that turns on the LED when the “if this” condition is met. To trigger our lantern, we could use any number of IFTTT channels, but for simplicity, let’s connect it up to the Yo smartphone app. Yo is a (rather silly) app that just lets you send a “yo” message to friends. The Yo channel for IFTTT allows you to trigger recipes by Yo-ing IFTTT. Load the app to your smartphone and add IFTTT as a contact by clicking the + button and typing “IFTTT” in the username field. If you haven’t already done so, create an IFTTT account and go to the “Channels” tab to activate the Yo and Spark channels. In both cases, you’ll have to log in to your respective accounts and authorize IFTTT. The process is straightforward and the IFTTT website walks you through the entire process. Once you’ve done this, you’re ready to create your first recipe. Click the “Create a Recipe” button found on the “My Recipes” tab. IFTTT will walk you through setting up both the trigger and action. For the “if this” condition, select your Yo channel and the “You Yo IFTTT” trigger. For the “then that” action, select the Spark channel and “Publish an event” action. Name the event (I just used “yo”) and select the “private event” option. (It doesn’t matter what you enter as the data field--we’re just going to ignore it anyway.) Name your recipe and click “Create Recipe” to finish the process. Your new recipe will now show up in your personal recipe list. Now we need to modify our Spark code to listen for our “yo” events. Back in the Spark Web IDE, change the code to the following. Now instead of turning the LED on and off in the loop() function, we instead register an event listener using Spark.subscribe() and turn the LED on for five seconds inside the callback function. int led = D0; void setup() { Spark.subscribe("yo", yoHandler, MY_DEVICES); pinMode(led, OUTPUT); } void loop() {} void yoHandler(const char *event, const char *data) { digitalWrite(led, HIGH); delay(5000); digitalWrite(led, LOW); } Once you’ve flashed this update to your Spark, it’s time to test it out! Be sure the Spark is flashing cyan (meaning it has a connection to the Spark cloud) and then use your smartphone to Yo IFTTT. The LED should light up for five seconds, then turn back off and wait again for the next “yo” event. Note that the “yo” events will be broadcast to all your Spark devices if you have more than one, so you could set up multiple hacked toys and send your greetings to several people at once. And if you choose to use public events, you could even trigger events to family and friends around the world.  All that’s left to do is package up the lantern by screwing everything back together. For a more permanent solution, instead of running the wires out to the external Spark, you could carefully fit the Spark and a small LiPo battery inside the lantern as well. I hope this post has inspired you to give new life to broken or disposable toys you have around the house. If you build something really cool, I’d love to see it. Consider sharing your project on the hackster.io Spark community. About the author David Resseguie is a member of the Computational Sciences and Engineering Division at Oak Ridge National Laboratory and lead developer for Sensorpedia. His interests include human computer interaction, Internet of Things, robotics, data visualization, and STEAM education. His current research focus is on applying social computing principles to the design of information sharing systems.
Read more
  • 0
  • 0
  • 3375

article-image-getting-started-twitter-flight
Packt
16 Oct 2013
6 min read
Save for later

Getting Started with Twitter Flight

Packt
16 Oct 2013
6 min read
(For more resources related to this topic, see here.) Simplicity First and foremost, Flight is simple. Most frameworks provide layouts, data models, and utilities that tend to produce big and confusing APIs. Learning curves are steep. In contrast, you'll probably only use 10 Flight methods ever, and three of those are almost identical. All components and mixins follow the same simple format. Once you've learned one, you've learned them all. Simplicity means fast ramp-up times for new developers who should be able to come to understand individual components quickly. Efficient complexity management In most frameworks, the complexity of the code increases almost exponentially with the number of features. Dependency diagrams often look like a set of trees, each with branches and roots intermingling to create a dense thicket of connections. A simple change in one place could easily create an unforeseen error in another or a chain of failures that could easily take down the whole application. Flight applications are instead built up from reliable, reusable artifacts known as components. Each component knows nothing of the rest of the application, it simply listens for and triggers events. Components behave like cells in an organism. They have well-defined input and output, are exhaustively testable, and are loosely coupled. A component's cellular nature means that introducing more components has almost no effect on the overall complexity of the code, unlike traditional architectures. The structure remains flat, without any spaghetti code. This is particularly important in large applications. Complexity management is important in any application, but when you're dealing with hundreds or thousands of components, you need to know that they aren't going to have unforeseen knock-on effects. This flat, cellular structure also makes Flight well-suited to large projects with large or remote development teams. Each developer can work on an independent component, without first having to understand the architecture of the entire application. Reusability Flight components have well-defined interfaces and are loosely coupled, making it easy to reuse them within an application, and even across different applications. This separates Flight from other frameworks such as Backbone or AngularJS, where functionality is buried inside layers of complexity and is usually impossible to extract. Not only does this make it easier and faster to build complex applications in Flight but it also offers developers the opportunity to give back to the community. There are already a lot of useful Flight components and mixins being open sourced. Try searching for "flight-" on Bower or GitHub, or check out the list at http://flight-components.jit.su/. Twitter has already been taking advantage of this reusability factor within the company, sharing components such as Typeahead (Twitter's search autocomplete) between Twitter.com and TweetDeck, something which would have been unimaginable a year ago. Agnostic architecture Flight has agnostic architecture. For example, it doesn't matter which templating system is used, or even if one is used at all. Server-side, client-side, or plain old static HTML are all the same to Flight. Flight does not impose a data model, so any method of data storage and processing can be used behind the scenes. This gives the developer freedom to change all aspects of the stack without affecting the UI and the ability to introduce Flight to an existing application without conflict. Improved Performance Performance is about a lot more than how fast the code executes, or how efficient it is with memory. Time to first load is a very important factor. When a user loads a web page, the request must be processed, data must be gathered, and a response will be sent. The response is then rendered by the client. Server-side processing and data gathering is fast. Latency and interpretation makes rendering slow. One of the largest factors in response and rendering speed is the sheer amount of code being sent over the wire. The more code required to render a page, the slower the rendering will be. Most modern JavaScript frameworks use deferred loading (for example, via RequireJS) to reduce the amount of code sent in the first response. However, all this code is needed to be able to render a page, because layout and templating systems only exist on the client. Flight's architecture allows templates to be compiled and rendered on the server, so the first response is a fully-formed web page. Flight components can then be attached to existing DOM nodes and determine their state from the HTML, rather than having to request data over XMLHttpRequest (XHR) and generate the HTML themselves. Well-organized freedom Back in the good old days of JavaScript development, it was all a bit of a free for all. Everyone had their own way of doing things. Code was idiosyncratic rather than idiomatic. In a lot of ways, this was a pain, that is, it was hard to onboard new developers and still harder to keep a codebase consistent and well-organized. On the other hand, there was very little boilerplate code and it was possible to get things done without having to first read lengthy documentation on a big API. jQuery built on this ideal, reduced the amount of boilerplate code required. It made JavaScript code easier to read and write, while not imposing any particular requirements in terms of architecture. What jQuery failed to do (and was never intended to do) was provide an application-level structure. It remained all too easy for code to become a spaghetti mess of callbacks and anonymous functions. Flight solves this problem by providing much needed structure while maintaining a simple, architecture-agnostic approach. Its API empowers developers, helping them to create elegant and well-ordered code, while retaining a sense of freedom. Put simply, it's a joy to use. Summary The Flight API is small and should be familiar to any jQuery user, producing a shallow learning-curve. The atomic nature of components makes them reliable and reusable, and creates truly scalable applications, while its agnostic architecture allows developers to use any technology stack and even introduce Flight into existing applications. Resources for Article: Further resources on this subject: Integrating Twitter and YouTube with MediaWiki [Article] Integrating Twitter with Magento [Article] Drupal Web Services: Twitter and Drupal [Article]
Read more
  • 0
  • 0
  • 3374
article-image-jsf-20-features
Packt
07 Jun 2010
6 min read
Save for later

JSF 2.0 Features

Packt
07 Jun 2010
6 min read
(For more resources on JSF, see here.) JSF 2.0 annotations One of the most important and useful features of JSF 2.0 consists in annotations. Based on them, JSF 2.0 provides an easy way to accomplish important tasks. In this recipe, we will present the most commonly used annotations and we will see what they can do for us. How to do it... If you are a JSF 1.2 fan, then you are familiar with the faces-config.xml configuration file. Starting with JSF 2.0, the content of this descriptor can be partially (sometimes totally) replaced with annotations. Annotations for managed beans The most common case is represented by the managed bean, which can be annotated as shown, instead of placing a specific declaration in faces-config.xml: import javax.faces.bean.ManagedBean;@ManagedBeanpublic class MyBean { ...} In the previous example, the bean is referenced as myBean, but you may specify another name, as shown next: @ManagedBean(name="coolBean") And what is a managed bean without a context (a scope)? JSF 2.0 supports an entire list of scope annotation, as shown next: Annotation Annotation Class @RequestScoped javax.faces.bean.RequestScoped @SessionScoped javax.faces.bean.SessionScoped @ApplicationScoped javax.faces.bean.ApplicationScoped @ViewScoped javax.faces.bean.ViewScoped @NoneScoped javax.faces.bean.NoneScoped @CustomScoped(value="#{someMap}") javax.faces.bean.CustomScoped In addition, we can annotate a managed bean's properties using the @ManagedProperty annotation . The presence of this annotation on a field of a class annotated with @ManagedBean instructs the system to inject a value into this property: @ManagedProperty("fooval")private String foo;@ManagedProperty("#{fooval}")private String foo; Going further, you can react to the creation and the destruction of a managed bean, as shown next: public class MyBean { @PostConstruct public void postCreate(){ ... } @PreDestroy public void preDestroy(){ ... } If you use JSF inside of a JEE container you can inject resources, session, message-driven beans, and web services into your managed beans. Something like the following is perfectly legal: @ManagedBean@SessionScopedpublic class MyBean implements Serializable { @EJB private Facade facade;... @ResourceDependency annotation JSF 2.0 specification has added the @ResourceDependency annotation to allow component authors to declare the resources the component will need. For example: @ResourceDependency(name="my.css",library="libus")public class MyComponent extends UIComponentBase { ...} You may use more than one @ResourceDependency using the @ResourceDependencies annotation, as the following: @ResourceDependencies({ @ResourceDependency(name="my.css",library="libus"),@ResourceDependency(name="my.js",library="libus",target="head")})public class MyComponent extends UIComponentBase { ...} Now the components can be used without any knowledge about any of the CSS or JS code. The necessary dependencies will be rendered automatically. The @ListenerFor annotation A component will be annotated with the @ListenerFor annotation to indicate that it is subscribing to a particular set of events. Therefore, we will have two renderers that act as listeners for particular events and that implement the ComponentSystemEventListener interface (a detailed description of this interface is available at http://blogs.sun.com/ rlubke/entry/jsf_2_0_new_feature1, but as a quick description, system events are new in JSF 2.0, and there are system events that are global and others that are related to a component. They are created at various moments of application or request lifetime). Let's see what this looks like: @ListenerFor(systemEventClass=AfterAddToParentEvent.class,sourceClass=UIOutput.class) public class MyRenderer extends Renderer implements ComponentSystemEventListener { ... public void processEvent(ComponentSystemEvent event) throws AbortProcessingException { UIComponent component = event.getComponent(); FacesContext context = FacesContext.getCurrentInstance(); String target = (String)component.getAttributes().get("target"); if (target != null) { context.getViewRoot().addComponentResource(context, component, target); } }...} There is also a plural version, named @ListenersFor. There is one more annotation in which we are interested, named @NamedEvent, which will be discussed in the JSF declarative event handling recipe. How it works... Annotations for managed beans Once you have annotated a class as a managed bean, it can be referred to as a bean with #{beanName.foo}, where beanName is class name (except packages) with the first letter changed to lower case, and "foo" is either an exact method name or a shortcut for a getter and setter method. Regarding managed beans scopes we have: @RequestScope: (this is the default scope of a managed bean). This puts the bean in request scope. It makes a new instance for every HTTP request. Commonly, the bean is instantiated twice, once when form is displayed and once when it is submitted. @SessionScope: This puts a Serializable bean in session scope. When the same user with the same cookie returns then the same bean instance is used (for this, the session timeout should not be expired). @ApplicationScoped: This puts the bean in application scope. All users will have access to this bean, therefore the bean either should have no state or you must manually and carefully synchronize access to it. @ViewScoped: This puts the bean in view scoped. The same bean instance is used as long as the same user is on same page (for example, with AJAX). @CustomScope: This puts the bean in custom scope. The bean is stored in the Map, and the developer can control its lifecycle. @NoneScope: The bean is not put in a scope. Commonly these beans are referenced by other beans that are in scopes. @ViewScoped, @CustomScoped and @NoneScoped are available only in JSF 2.0. @ResourceDependency annotation Once a component is created, it will be added as a child to another component. Before returning from the add() method, the component will be checked for @ResourceDependency annotations (both versions). When the @ResourceDependency is found a new UIOutput component instance is created. The ResourceHandler is queried for an appropriate Renderer based on the content type of the resource. In our case this is text/css, therefore the style sheet renderer will be used as the Renderer for this UIOutput component. The values of the name, library (optional), and target (optional) attributes from the annotation are stored in the component's attribute map. UIViewRoot. addComponentResource() is called passing in the UIOutput and the value of the target attribute from the annotation (if exists). Now when we render the view, for the head renderer we encode each of the resources that have been targeted for the head, like so: ...UIViewRoot viewRoot = context.getViewRoot();for (UIComponent ui_comp:viewRoot.getComponentResources(context,"head")) {ui_comp.encodeAll(context);}... The @ListenerFor annotation When the Renderer for this component is obtained it is queried for @ListenerFor annotations. For each annotation, the Renderer will be added as a component listener for the corresponding event. Going further, when the component is added in the tree, the event is invoked and the processEvent method will be called for adding the component as a resource to the VewRoot with the corresponding target.
Read more
  • 0
  • 0
  • 3373

article-image-user-authentication-codeigniter-17-using-twitter-oauth
Packt
21 May 2010
6 min read
Save for later

User Authentication with Codeigniter 1.7 using Twitter oAuth

Packt
21 May 2010
6 min read
(Read more interesting articles on CodeIgniter 1.7 Professional Development here.) How oAuth works Getting used to how Twitter oAuth works takes a little time. When a user comes to your login page, you send a GET request to Twitter for a set of request codes. These request codes are used to verify the user on the Twitter website. The user then goes through to Twitter to either allow or deny your application access to their account. If they allow the application access, they will be taken back to your application. The URL they get sent to will have an oAuth token appended to the end. This is used in the next step. Back at your application, you then send another GET request for some access codes from Twitter. These access codes are used to verify that the user has come directly from Twitter, and has not tried to spoof an oAuth token in their web browser. Registering a Twitter application Before we write any code, we need to register an application with Twitter. This will give us the two access codes that we need. The first is a consumer key, and the second is a secret key. Both are used to identify our application, so if someone posts a message to Twitter through our application, our application name will show up alongside the user's tweet. To register a new application with Twitter, you need to go to http://www.twitter.com/apps/new. You'll be asked for a photo for your application and other information, such as website URL, callback URL, and a description, among other things. You must select the checkbox that reads Yes, use Twitter for login or you will not be able to authenticate any accounts with your application keys. Once you've filled out the form, you'll be able to see your consumer key and consumer secret code. You'll need these later. Don't worry though; you'll be able to get to these at any time so there's no need to save them to your hard drive. Here's a screenshot of my application: Downloading the oAuth library Before we get to write any of our CodeIgniter wrapper library, we need to download the oAuth PHP library. This allows us to use the oAuth protocol without writing the code from scratch ourselves. You can find the PHP Library on the oAuth website at www.oauth.net/code. Scroll down to PHP and click on the link to download the basic PHP Library; or just visit: http://oauth.googlecode.com/svn/code/php/—the file you need is named OAuth.php. Download this file and save it in the folder system/application/libraries/twitter/—you'll need to create the twitter folder. We're simply going to create a folder for each different protocol so that we can easily distinguish between them. Once you've done that, we'll create our Library file. Create a new file in the system/application/libraries/ folder, called Twitter_oauth.php. This is the file that will contain functions to obtain both request and access tokens from Twitter, and verify the user credentials. The next section of the article will go through the process of creating this library alongside the Controller implementation; this is because the whole process requires work on both the front-end and the back-end. Bear with me, as it could get a little confusing, especially when trying to implement a brand new type of system such as Twitter oAuth. Library base class Let's break things down into small sections. The following code is a version of the base class with all its guts pulled out. It simply loads the oAuth library and sets up a set of variables for us to store certain information in. Below this, I'll go over what each of the variables are there for. <?phprequire_once(APPPATH . 'libraries/twitter/OAuth.php');class Twitter_oauth{ var $consumer; var $token; var $method; var $http_status; var $last_api_call;}?> The first variable you'll see is $consumer—it is used to store the credentials for our application keys and the user tokens as and when we get them. The second variable you see on the list is $token—this is used to store the user credentials. A new instance of the oAuth class OAuthConsumer is created and stored in this variable. Thirdly, you'll see the variable $method—this is used to store the oAuth Signature Method (the way we sign our oAuth calls). Finally, the last two variables, $http_status and $last_api_call, are used to store the last HTTP Status Code and the URL of the last API call, respectively. These two variables are used solely for debugging purposes. Controller base class The Controller is the main area where we'll be working, so it is crucial that we design the best way to use it so that we don't have to repeat our code. Therefore, we're going to have our consumer key and consumer secret key in the Controller. Take a look at the Base of our class to get a better idea of what I mean. <?phpsession_start();class Twitter extends Controller{ var $data; function Twitter() { parent::Controller(); $this->data['consumer_key'] = ""; $this->data['consumer_secret'] = "";} The global variable $data will be used to store our consumer key and consumer secret. These must not be left empty and will be provided to you by Twitter when creating your application. We use these when instantiating the Library class, which is why we need it available throughout the Controller instead of just in one function. We also allow for sessions to be used in the Controller, as we want to temporarily store some of the data that we get from Twitter in a session. We could use the CodeIgniter Session Library, but it doesn't offer us as much flexibility as native PHP sessions; this is because with native sessions we don't need to rely on cookies and a database, so we'll stick with the native sessions for this Controller.
Read more
  • 0
  • 0
  • 3370

article-image-building-puppet-module-skeleton
Packt
13 May 2016
5 min read
Save for later

Building a Puppet Module Skeleton

Packt
13 May 2016
5 min read
In this article by Scott Coulton, author of the book, Puppet for Containerization, we are going to look at how to construct a Puppet module with the correct file structure, unit tests, and gems. One of the most important things in development is having a solid foundation. Writing a Puppet module is no different. This topic is extremely important for the rest of the book, as we will be reusing the code over and over again to build all our modules. Let's look at how to build a module with the Puppet module generator. (For more resources related to this topic, see here.) The Puppet module generator One of the best things about working with Puppet is the number of tools out there both from the community and from Puppetlabs itself. The Puppet module generator is a tool that is developed by Puppetlabs and follows the best practices to create a module skeleton. The best thing about this tool is that it is bundled with every Puppet agent install. So, we don't need to install any extra software. So, let's log in to our vagrant box that we built in the last chapter. Let's change the directory to the root of our Vagrant repo and then use the vagrant up && vagrant ssh command. Now that we are logged in to the box, let's change the directory to root (sudo -i) and change the directory to /vagrant. The reason for this is that this folder will be mapped to our local box. Then, we can use our favorite text editor later in the chapter. Once we're in /vagrant, we can run the command to build our Puppet module skeleton. The puppet module generate <AUTHOR>-consul command for me will look like this: puppet module generate scottyc-consul. The script will then ask a few questions such as the version, author name, description, where the source lives, and so on. These are very important questions that are to be considered when you want to publish a module to the Forge (https://forge.puppetlabs.com/), but for now, let's just answer the questions as per the following example: Now that we have our Puppet module skeleton, we should look at what the structure looks like: Now, we are going to add a few files to help us with unit tests. The first file is .fixtures.yml. This file is used by spec-puppet to pull down any module dependencies into the spec/fixtures directory when we run our unit tests. For this module, the .fixtures.yml file should like as shown in the following screenshot: The next file that we are going to add is a .rspec file. This is the file that spec-puppet uses when it requires spec_helper and sets the pattern for our unit test folder structure. The file contents should look like as shown in this screenshot: Now that we have our folder structure, let's install the gems that we need to run our unit tests. My personal preference is to install the gems on the vagrant box; if you want to use your local machine, that's fine as well. So, let's log in to our vagrant box (cd into the root of our Vagrant repo and use the vagrant ssh command and then change the directory to root using sudo -i). First, we will install Ruby with yum install -y ruby. Once that is complete, let's cd into /vagrant/<your modules folder> and then run gem install bundler && bundle install. You should get the following output after this: As you can see from the preceding screenshot, we got some warnings. This is because we ran gem install as the root. We would not do that on a production system, but as this is our development box, it wont pose an issue. Now that we have all the gems that we need for our unit tests, let's add some basic facts to /spec/classes/init_spec.rb. The facts we are going to add are osfamily and operatingsystemrelease. So, the file will look like as shown in this screenshot: The last file that we will edit is the metadata.json file in the root of the repo. This file defines our module dependencies. For this module, we have one dependency, that is, docker, so we need to add that at the bottom of the metadata.json file, as shown in the following screenshot: The last thing we need to do is put everything in its place inside our Vagrant repo. We do that by creating a folder called modules in the root of our Vagrant repo. Then, we issue the mv <AUTHOR>-consul/ modules/consul command. Note that we removed the author name because we need the module to replicate what it would look like on a Puppet master. Now that we have our basic module skeleton ready, we can start with some coding. Summary So in this article we covered how to build a module with the Puppet module generator. For more information on Puppet, you can check other books by Packt Publsihing, mentioned as follows: Learning Puppet Puppet 3: Beginner’s Guide Mastering Puppet Resources for Article: Further resources on this subject: Puppet and OS Security Tools [article] Puppet Language and Style [article] Module, Facts, Types and Reporting tools in Puppet [article]
Read more
  • 0
  • 0
  • 3370
article-image-parallel-computing
Packt
30 Sep 2016
9 min read
Save for later

Parallel Computing

Packt
30 Sep 2016
9 min read
In this article written by Jalem Raj Rohit, author of the book Julia Cookbook, cover the following recipes: Basic concepts of parallel computing Data movement Parallel map and loop operations Channels (For more resources related to this topic, see here.) Introduction In this article, you will learn about performing parallel computing and using it to handle big data. So, some concepts like data movements, sharded arrays, and the map-reduce framework are important to know in order to handle large amounts of data by computing on it using parallelized CPUs. So, all the concepts discussed in this article will help you build good parallel computing and multiprocessing basics, including efficient data handling and code optimization. Basic concepts of parallel computing Parallel computing is a way of dealing with data in a parallel way. This can be done by connecting multiple computers as a cluster and using their CPUs for carrying out the computations. This style of computation is used when handling large amounts of data and also while running complex algorithms over significantly large data. The computations are executed faster due to the availability of multiple CPUs running them in parallel as well as the direct availability of RAM to each of them. Getting ready Julia has an in-built support for parallel computing and multiprocessing. So, these computations rarely require any external libraries for the task. How to do it… Julia can be started in your local computer using multiple cores of your CPU. So, we will now have multiple workers for the process. This is how you can fire up Julia in the multi-processing mode in your terminal. This creates two worker process in the machine, which means it uses twwo CPU cores for the purpose julia -p 2 The output looks something like this. It might differ for different operating systems and different machines: Now, we will look at the remotecall() function. It takes in multiple arguments, the first one being the process which we want to assign the task to. The next argument would be the function which we want to execute. The subsequent arguments would be the parameters or the arguments of that function which we want to execute. In this example, we will create a 2 x 2 random matrix and assign it to the process number 2. This can be done as follows: task = remotecall(2, rand, 2, 2) The preceding command gives the following output: Now that the remotecall() function for remote referencing has been executed, we will fetch the results of the function through the fetch() function. This can be done as follows: fetch(task) The preceding command gives the following output: Now, to perform some mathematical operations on the generated matrix, we can use the @spawnat macro, which takes in the mathematical operation and the fetch() function. The @spawnat macro actually wraps the expression 5 .+ fetch(task) into an anonymous function and runs it on the second machine This can be done as follows: task2 = @spawnat 5 .+ fetch(task) There is also a function that eliminates the need of using two different functions: remotecall() and fetch(). The remotecall_fetch() function takes in multiple arguments. The first one being the process that the task is being assigned. The next argument is the function which you want to be executed. The subsequent arguments would be the arguments or the parameters of the function that you want to execute. Now, we will use the remote call_fetch() function to fetch an element of the task matrix for a particular index. This can be done as follows: remotecall_fetch(2, getindex, task2, 1, 1) How it works… Julia can be started in the multiprocessing mode by specifying the number of processes needed while starting up the REPL. In this example, we started Julia as a two process mode. The maximum number of processes depends on the number of cores available in the CPU. The remotecall() function helps in selecting a particular process from the running processes in order to run a function or, in fact, any computation for us. The fetch() function is used to fetch the results of the remotecall() function from a common data resource (or the process) for all the running processes. The details of the data source would be covered in the later sections. The results of the fetch() function can also be used for further computations, which can be carried out with the @spawnat macro along with the results of fetch(). This would assign a process for the computation. The remotecall_fetch() function further eliminates the need for the fetch function in case of a direct execution. This has both the remotecall() and fetch() operations built into it. So, it acts as a combination of both the second and third points in this section. Data movement In parallel computing, data movements are quite common and are also a thing to be minimized due to the time and the network overhead due to the movements. In this recipe, we will see how that can be optimized to avoid latency as much as we can. Getting ready To get ready for this recipe, you need to have the Julia REPL started in the multiprocessing mode. This is explained in the Getting ready section of the preceding recipe. How to do it… Firstly, we will see how to do a matrix computation using the @spawn macro, which helps in data movement. So, we construct a matrix of shape 200 x 200 and then try to square it using the @spawn macro. This can be done as follows: mat = rand(200, 200) exec_mat = @spawn mat^2 fetch(exec_mat) The preceding command gives the following output: Now, we will look at an another way to achieve the same. This time, we will use the @spawn macro directly instead of the initialization step. We will discuss the advantages and drawbacks of each method in the How it works… section. So, this can be done as follows: mat = @spawn rand(200, 200)^2 fetch(mat) The preceding command gives the following output: How it works… In this example, we try to construct a 200X200 matrix and then used the @spawn macro to spawn a process in the CPU to execute the same for us. The @spawn macro spawns one of the two processes running, and it uses one of them for the computation. In the second example, you learned how to use the @spawn macro directly without an extra initialization part. The fetch() function helps us fetch the results from a common data resource of the processes. More on this will be covered in the following recipes. Parallel maps and loop operations In this recipe, you will learn a bit about the famous Map Reduce framework and why it is one of the most important ideas in the domains of big data and parallel computing. You will learn how to parallelize loops and use reducing functions on them through the several CPUs and machines and the concept of parallel computing, which you learned about in the previous recipes. Getting ready Just like the previous sections, Julia just needs to be running in the multiprocessing mode to follow along the following examples. This can be done through the instructions given in the first section. How to do it… Firstly, we will write a function that takes and adds n random bits. The writing of this function has nothing to do with multiprocessing. So, it has simple Julia functions and loops. This function can be written as follows: Now, we will use the @spawn macro, which we learned previously to run the count_heads() function as separate processes. The count_heads()function needs to be in the same directory for this to work. This can be done as follows: require("count_heads") a = @spawn count_heads(100) b = @spawn count_heads(100) fetch(a) + fetch(b) However, we can use the concept of multi-processing and parallelize the loop directly as well as take the sum. The parallelizing part is called mapping, and the addition of the parallelized bits is called reduction. Thus, the process constitutes the famous Map-Reduce framework. This can be made possible using the @parallel macro, as follows: nheads = @parallel (+) for i = 1:200 Int(rand(Bool)) end How it works… The first function is a simple Julia function that adds random bits with every loop iteration. It was created just for the demonstration of Map-Reduce operations. In the second point, we spawn two separate processes for executing the function and then fetch the results of both of them and add them up. However, that is not really a neat way to carry out parallel computation of functions and loops. Instead, the @parallel macro provides a better way to do it, which allows the user to parallelize the loop and then reduce the computations through an operator, which together would be called the Map-Reduce operation. Channels Channels are like the background plumbing for parallel computing in Julia. They are like the reservoirs from where the individual processes access their data from. Getting ready The requisite is similar to the previous sections. This is mostly a theoretical section, so you just need to run your experiments on your own. For that, you need to run your Julia REPL in a multiprocessing mode. How to do it… Channels are shared queues with a fixed length. They are common data reservoirs for the processes which are running. The channels are like common data resources, which multiple readers or workers can access. They can access the data through the fetch() function, which we already discussed in the previous sections. The workers can also write to the channel through the put!() function. This means that the workers can add more data to the resource, which can be accessed by all the workers running a particular computation. Closing a channel after usage is a good practice to avoid data corruption and unnecessary memory usage. It can be done using the close() function. Summary In this article we covered the basic concepts of parallel computing and data movement that takes place in the network. We also learned about parallel maps and loop operations along with the famous Map Reduce framework. At the end we got a brief understanding of channels and how individual processes access their data from channels. Resources for Article: Further resources on this subject: More about Julia [article] Basics of Programming in Julia [article] Simplifying Parallelism Complexity in C# [article]
Read more
  • 0
  • 0
  • 3370

article-image-examining-oracle-architecture
Packt
19 Apr 2013
17 min read
Save for later

Examining the Oracle Architecture

Packt
19 Apr 2013
17 min read
(For more resources related to this topic, see here.) Understanding the Oracle RDBMS The term RDBMS, or Relational Database Management System can be used in many ways and, more often than not, simply refers to a commercial database management product. However, the true meaning of the term RDBMS refers to the way the product operates internally to store and retrieve data. There are many commercial and open source database management systems available today. While they all attempt to interface with the user in a manner that is generally compliant with international standards, they all operate differently internally. We will explore the characteristics that make the Oracle RDBMS unique and, in doing so, understand how it works. Distinguishing between an instance and a database To define the Oracle database architecture, we must first define two terms and make a distinction between them. An instance is the set of background processes and memory structures that enable the Oracle kernel to operate. A database is the set of files that stores the data contained in the RDBMS. These two entities account for the three basic resources available to computers, namely the CPU, RAM, and disk. The instance represents the usage of the CPU and RAM, while the database represents the usage of the disk. These definitions are architecturally oriented, and the distinction between the two isn't always fully recognized. In fact, the two are often used interchangeably. In most database configurations, it is reasonable to do so since, on a single server, the instance and database operate together. However, it's important to draw a distinction at this point, for three reasons. First, the terms themselves are used differently with other RDBMS products, such as Microsoft SQL Server. Secondly, when investigating the Oracle architecture, it is simpler to see the relationship between the various architectural components if we divide them accordingly. Lastly, although an instance and a database generally operate together on a single server, other database configurations are possible. In Oracle's Real Application Clusters, or RAC, the instance and database are both logically and physically separated. We will examine the subject of RAC later in the article. The following diagram gives us a broad look of the Oracle architecture as a whole. We will refer back to portions of it throughout the article: Note that this is a logical diagram that groups similar functions together. We display this as a reverse tree diagram. The top of the tree is the RDBMS itself. From there, it branches into the instance and the database, the terms we have just defined. We will look at each branch of this diagram and examine the individual components, as well as how they operate and contribute to the inner working of the Oracle RDBMS. Examining the Oracle instance As we mentioned before, the Oracle instance is composed of the necessary processes and memory structures required to operate the Oracle kernel. The instance is the first thing invoked when the database is started. Recognizing the primary Oracle processes The first components of the Oracle instance that we will examine are the Oracle background processes. These processes run in the background of the operating system and are not interacted with directly. Each process is highly specialized and has a specific function in the overall operation of the Oracle kernel. While these processes accomplish the same functions regardless of the host operating system, their implementation is significantly different. On Unix-based systems, owing to Unix's multiprocess architecture, each Oracle process runs as a separate operating system process. Thus, we can actually see the processes themselves from within the operating system. For instance, we can use the ps command on Linux to see these processes, as shown in the following screenshot. We've highlighted a few of them that we will examine in depth. Note that our background processes are named in the format ora_ processtype_SID. Since the SID for our database is ORCL, that name forms a part of the full process name: On Windows, rather than implementing each Oracle process as a separate OS process, the Oracle processes are implemented as threads since Windows is a multithreaded operating system. As a result, the Oracle kernel runs under a single executable called Oracle.exe. The background processes then run as threads under that single process. So, if we attempt to see the Oracle background processes using Windows's Task Manager, we only see the Oracle.exe executable, as shown in the next screenshot. The threads representing the Oracle processes are masked to us, at least at the operating system level: We can also display this information from the Windows command line by running the tasklist command: Regardless of whether we can see each process directly from the operating system, once the instance starts, they are present. Each has a specific job and all run in concert to service the needs of the database. PMON – the Process Monitor The core process of the Oracle architecture is the PMON process—the Process Monitor. The PMON is tasked with monitoring and regulating all other Oracle-related processes. This includes not only background processes but server processes as well. Most databases run in a dedicated server mode. In this mode, any user that connects to the database is granted a server process with which to do work. In Linux systems, this process can actually be viewed at the server level with the ps -ef command. When the user connects over the network, the process will be labeled with LOCAL=NO in the process description. Privileged users such as database administrators can also make an internal connection to the database, provided that we are logging in from the server that hosts the database. When an internal connection is made, the process is labeled with LOCAL=YES. We see an example of each in the following screenshot of the ps –ef command on a Linux machine hosting Oracle: Under ordinary circumstances, when a user properly disconnects his or her session from the database by exiting the tool used to connect to it, the server process given to that user terminates cleanly. However, what if instead of disconnecting the connection properly, the machine that the user was connected to was rebooted? In situations like these, the server process on the database is left running since it hasn't received the proper instructions to terminate. When this occurs, it is the job of PMON to monitor sessions and clean up orphaned processes. The PMON normally "wakes up" every 3 seconds to check these processes and clean them up. In addition to this primary function, PMON is also responsible for registering databases with network listeners. The real-world DBA Since the instance cannot run unless PMON is running, DBAs sometimes check for it using the ps command as a way of determining whether the instance is down, because, on Unix-based systems, we can actually see the processes at the server level using the command ps –ef | grep pmon. If a process is not returned, we know the instance is down. SMON – the System Monitor The SMON, or System Monitor process, has several very important duties. Chiefly SMON is responsible for instance recovery. Under normal circumstances, databases are shut down using the proper commands to do so. When this occurs, all of the various components, mainly the datafiles, are properly recorded and synchronized so that the database is left in a consistent state. However, if the database crashes for some reason (the database's host machine loses power, for instance), this synchronization cannot occur. When the database is restarted, it will begin from an inconsistent state. Every time the instance is started, SMON will check for these marks of synchronization. In a situation where the database is in an inconsistent state, SMON will perform instance recovery to resynchronize these inconsistencies. Once this is complete, the instance and database can open correctly. Unlike database recovery, where some data loss has occurred, instance recovery occurs without intervention from the DBA. It is an automatic process that is handled by SMON. The SMON process is also responsible for various cleanup operations within the datafiles themselves. tempfiles are the files that hold the temporary data that is written when an overflow from certain memory caches occurs. This temporary data is written in the form of temporary segments within the tempfile. When this data is no longer needed, SMON is tasked with removing them. The SMON process can also coalesce data within datafiles, removing gaps, which allows the data to be stored more efficiently. DBWn – the Database Writer process For all of the overhead duties of processes such as PMON and SMON, we can probably intuit that there must be a process that actually reads and writes data from the datafiles. Until later versions, that process was named DBWR – the Database Writer process. The DBWR is responsible for reading and writing the data that services user operations, but it doesn't do it in the way that we might expect. In Oracle, almost no operation is executed directly on the disk. The Oracle processing paradigm is to read data into memory, complete a given operation while the data is still in memory, and write it back to the disk. We will cover the reason for this in greater depth when we discuss memory caches, but for now let's simply say it is for performance reasons. Thus, the DBWR process will read a unit of data from the disk, called a database block, and place it into a specialized memory cache. If data is changed using an UPDATE statement, for instance, it is changed in memory. After some time, it is written back to the disk in its new state. If we think about it, it should be obvious that the amount of reading and writing in a database would constitute a great deal of work for one single process. It is certainly possible that a single DBWR process would become overloaded and begin to affect performance. That's why, in more recent versions of Oracle, we have the ability to instantiate multiple database writer processes. So we can refer to DBWR as DBWn, where "n" is a given instantiation of a database writer process. If our instance is configured to spawn three database writers, they would be dbw0, dbw1, and dbw2. The number of the DBWn processes that are spawned is governed by one of our initialization parameters, namely, db_writer_processes. Let's take a closer look at how the value for db_writer_processes affects the database writer processes that we can see in the Linux operating system. We won't go into great depth with the commands that we'll be using at this point, but we can still see how the spawning of multiple DBWn processes works. We will become very familiar with commands such as these as we revisit them frequently throughout many of the examples in this book. First, let's examine the number of DBWn processes on our system using the ps command, with which we're familiar: From the Linux command line, we use the ps –ef command along with the grep command that searches through the processes in the system with the string dbw in their names. This restricts our output to only those processes that contain dbw, which will be the database writer processes. As we can see in the preceding screenshot, there is only one database writer process named ora_dbw0_orcl. As mentioned, the number of the database writer processes is determined by an initialization parameter. The name of that parameter is db_writer_processes.We can determine the value of this parameter by logging into the database using SQL*Plus (the command sqlplus / as sysdba) and showing its value using the show parameter command, as in the following screenshot: Since we've already determined that we only have a single dbw0 process, it should come as no surprise that the value for our parameter is 1. However, if we wish to add more database writers, it is simple to do so. From the SQL*Plus command line, we issue the following command, followed by the shutdown immediate and startup commands to shut down and start up the database: The alter system command instructs Oracle to set the db_writer_processes parameter to 4. The change is recognized when the database is restarted. From here, we type exit to leave SQL*Plus and return to the Linux command line. We then issue our ps command again and view the results: As we can see in the preceding screenshot, there are four database writer processes, called ora_dbw0_orcl, ora_dbw1_orcl, ora_dbw2_orcl, and ora_dbw3_orcl, that align with our value for db_writer_processes. We now have four database writer processes with which to read and write data. The real-world DBA What's the optimal number of database writers? The answer is that, as with many aspects of database administration, it depends. The parameter has a maximum value of 20, so does that mean more is better? Not necessarily. The simplest answer is that the default value, either 1 or the integer value resulting from the number of CPUs divided by 8 (whichever is greater), will generally provide the best performance. Most opinions regarding best practices vary greatly and are usually based on the number of CPUs in the host box. Generally, the default value will serve you well unless your server is very large or heavy tuning is needed. CKPT – the Checkpoint process We mentioned in the preceding section that the purpose of the DBWn process is to move data in and out of memory. Once a block of data is moved into memory, it is referred to as a buffer. When a buffer in memory is changed using an UPDATE statement, for instance, it is called a dirty buffer. Dirty buffers can remain in memory for a time and are not automatically flushed to disk. The event that signals the writing of dirty buffers to disk is known as a checkpoint. The checkpoint ensures that memory is kept available for other new buffers and establishes a point for recovery. In earlier versions of Oracle, the type of checkpoint that occurred was known as a full checkpoint. This checkpoint will flush all dirty buffers back to the datafiles on the disk. While full checkpoints represent a complete flush of the dirty buffers, they are expensive in terms of performance. Since Version 8i, the Oracle kernel makes use of an incremental checkpoint that intelligently flushes only part of the available dirty buffers when needed. Full checkpoints only occur now during a shutdown of the database or on demand, using a command. The process in the instance that orchestrates checkpointing is the CKPT process. The CKPT process uses incremental checkpoints at regular intervals to ensure that dirty buffers are written out and any changes recorded in the redo logs are kept consistent for recovery purposes. Unlike the DBWn process, there is only one CKPT process. Although the incremental checkpoint method is used by CKPT, we can also force a full checkpoint using the command shown in the following screenshot: LGWR – the Log Writer process Redo logs are files that serially store the changes that occur in the database. These changes can be anything from INSERT, DELETE, or UPDATE statements executed against the database to the creation of new tables. Note, however, that queries against the database using SELECT statements do not constitute changes and are not recorded in the redo logs. The primary function of redo logs is to act during database recovery, where database changes can be "rolled forward" from a backup. When a change occurs in the database, that change is first written into a memory buffer called the log buffer that is specifically tasked with handling database changes. It is then written into the redo logs. The process that writes changes from memory to disk is the LGWR process. There is only one LGWR process, so it is important that it moves data as efficiently as possible. There are three conditions that can occur to cause LGWR to move changes from memory into the redo logfiles: When a COMMIT command is issued When the log buffer fills to one-third of its capacity Every three seconds The last of these conditions, "every three seconds," is actually caused by the DBWn process. The database writer has a three-second timeout before it must write a limited number of dirty buffers to disk. When this occurs, the LGWR process also flushes its changes just before DBWn does its work. This ensures that uncommitted transactions can always be rolled back. ARCn – the Archiver process The ARCH, or the Archiver process, is an optional but very important process. Let's continue describing the life cycle of a change in Oracle. To review, as sessions change data, those changes are written into the log buffer. At periodic intervals, those changes are written out serially to the redo logs by the LGWR process. The number and size of the redo logs can vary, but there are always a limited number of them. When one redo log becomes full, LGWR switches to the next one. Since there are a finite number of redo logs, LGWR eventually fills them all. When that happens, LGWR switches back to the original redo log and overwrites the changes that exist in the log. This effectively destroys those changes and invalidates the purpose of storing the changes at all. When the database operates in this manner, overwriting changes that were stored in the redo logs, we say that we're operating in NOARCHIVELOG mode. In order to prevent changes from being overwritten, we must operate using a different mode—ARCHIVELOG mode. When the database is in ARCHIVELOG mode, the contents of the redo logs are written out to a different type of file called archive logs. Archive logs simply contain the data that was in the redo log and serve as its static copy. However, archive logs never overwrite each other. Thus, the history of changes stored in the archive logs and redo logs constitute all the changes that have occurred from a given point in time. The process that enables ARCHIVELOG mode is the Archiver process, or ARCH. The ARCH copies data from the redo logs to the archive logs and does so before the data in the redo logs can be overwritten. Like DBWn, the Archiver process can run as multiple processes, albeit with a different purpose. In previous versions of Oracle, the Archiver process ran as a single process— ARCH. In recent versions, it is more accurate to call the Archiver process by its proper name, ARCn, where "n" is the number for one of multiple Archiver processes. When ARCn runs as multiple processes, it does so in order to write to multiple locations, rather than using multiple processes to write to a single location. Since, along with the redo logs, the archive logs contain all of the changes that have occurred in the database, they are critical to database recovery. As such, we can configure our database to write out archive log copies to more than one location. For instance, we may want to configure the Archiver process to write archive logs to two different locations on disk or write a copy of them out to a tape drive to mitigate the risk of data loss.
Read more
  • 0
  • 1
  • 3368
Modal Close icon
Modal Close icon