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-ajaxdynamic-content-and-interactive-forms-joomla
Packt
16 Oct 2009
13 min read
Save for later

AJAX/Dynamic Content and Interactive Forms in Joomla!

Packt
16 Oct 2009
13 min read
AJAX: an acronym that Jesse James Garret of AdaptivePath.com came up with in 2005. Just a few short years later, it seems like every site has a "taste" of AJAX in it. If you're totally new to AJAX, I'll just point out that, at its core, AJAX is nothing very scary or horrendous. AJAX isn't even a new technology or language. Essentially, AJAX stands for: Asynchronous JavaScript and XML, and it is the technique of using JavaScript and XML to send and receive data between a web browser and a web server. The biggest advantage this technique has is that you can dynamically update a piece of content on your web page or web form with data from the server (preferably formatted in XML), without forcing the entire page to reload. The implementation of this technique has made it obvious to many web developers that they can start making advanced web applications (sometimes called RIAs—Rich Interface Applications) that work and feel more like software applications than web pages. Keep in mind that the word AJAX is starting to have its own meaning (as you'll also note its occasional use here as well as all over the Web as a proper noun rather than an all-cap acronym). For example, a Microsoft web developer may use VBScript instead of JavaScript to serve up Microsoft Access database data that is transformed into JSON (not XML) using a .NET server-side script. Today, that guy's site would still be considered an AJAX site rather than an "AVAJ" site (yep, AJAX just sounds cooler). In fact, it's getting to the point where just about anything on a web site (that isn't in Flash) that slides, moves, fades, or pops up without rendering a new browser window is considered an "Ajaxy" site. In truth, a large portion of these sites don't truly qualify as using AJAX, they're just using straight-up JavaScripting. Generally, if you use cool JavaScripts in your Joomla! site, it will probably be considered Ajaxy, despite not being asynchronous or using any XML. Want more info on this AJAX business? The w3schools site has an excellent introduction to AJAX, explaining it in straightforward simple terms. They even have a couple of great tutorials that are fun and easy to accomplish even if you only have a little HTML, JavaScript and server-side script (PHP or ASP) experience (no XML experience required): http://w3schools.com/ajax/. Preparing for dynamic content and interactive forms Gone are the days of clicking, submitting, and waiting for the next page to load, or manually compiling your own content from all your various online identities to post in your site. A web page using AJAX techniques (if applied properly) will give the user a smoother and leaner experience. Click on a drop-down option and check-box menus underneath are immediately updated with the relevant choices—no submitting, no waiting. Complicated forms that, in the past, took two or three screens to process can be reduced into one convenient screen by implementing the form with AJAX. As wonderful as this all sounds, I must again offer a quick disclaimer: I understand that, like with drop-down menus and Flash, you may want AJAX to be in your site, or your clients are demanding that AJAX be in their sites. Just keep in mind, AJAX techniques are best used in situations where they truly benefit a user's experience of a page; for example, being able to painlessly add relevant content via an extension or cutting a lengthy web process form down from three pages to one. In a nutshell, using an AJAX technique simply to say your site is an AJAX site is probably not a good idea. You should be aware that, if not implemented properly, some uses of AJAX can compromise the security of your site. You may inadvertently end up disabling key web browser features (such as back buttons or the history manager). Then there's all the basic usability and accessibility issues that JavaScript in general can bring to a site. Some screen readers may not be able to read a new screen area that's been generated by JavaScript. If you cater to users who rely on tabbing through content, navigation may be compromised once new content is updated. There are also interface design problems that AJAX brings to the table (and Flash developers can commiserate). Many times, in trying to limit screen real estate and simplify a process, developers actually end up creating a form or interface that is unnecessarily complex and confusing, especially when your user is expecting a web page to, well, act like a normal web page. Remember to check in with Don't Make Me Think: This is the Steve Krug book I recommend for help with any interface usability questions you may run into.Really interested in taking on AJAX? For you programmers, I highly recommend "AJAX and PHP: Building Responsive Web Applications", Cristian Darie, Bogdan Brinzarea, Filip Chereches-Tosa, and Mihai Bucica, Packt Publishing. In it, you'll learn the ins and outs of AJAX development, including handling security issues. You'll also do some very cool stuff, such as make your own Google-style auto-suggest form and a drag-and-drop sortable list (and that's just two of the many fun things to learn in the book). So, that said, you're now all equally warned and armed with all the knowledgeable resources I can think to throw at you. Let's get to it: how exactly do you go about getting something Ajaxy into your Joomla! site? Joomla! extensions Keep in mind, extensions are not part of your template. They are additional files with Joomla!-compatible PHP code, which are installed separately into their own directories in your Joomla! 1.5 installation. Once installed, they are available to be used with any template that is also installed in your Joomla! installation. Even though these are not part of your template, you might have to prepare your template to be fully compatible with them. Some extensions may have their own stylesheets, which are installed in their extension directory. Once you've installed an extension, you may want to go into your own template's stylesheet so that it nicely displays XHTML objects and content that the extension may output into your site. Extensions are any component, module or plugin that you install into your Joomla! 1.5 installation. Components control content that displays in the main type="component" jdoc tag in your template. Note that components may also have module settings and the ability to display content in assigned module positions. The poll component is a good example of a component that also has module settings. Modules are usually smaller and lighter and only display in module positions. Plugins generally help you out more on the backend of your site, say to switch WYSIWYG editors or with enabling OpenID logins, but as we'll see, some plugins can affect the display of your site to users as well. Deciding where AJAX is best used On the whole, we're going to look at the most popular places where AJAX can really aid and enrich your site's user experience. We'll start with users adding comments to articles and pages and streamlining that process. We'll then take a look at a nice plugin that can enhance pagination for people reading long articles on your site. We'll then move on to the RSS Reader module, which can enhance the content in your modules (and even makes your users have fun arranging them). Finally, we'll realize that AJAX isn't just for impressing your site users. You, as an administrator, can (and do) take advantage of AJAX as well. Please note: These extensions were chosen by me based on the following criteria: 1. They provided some useful enhancement to a basic site.2. They, at the time of this writing, were free and received very good feedback on Joomla!.org's extensions site: http://extensions.Joomla.org. In the next few pages, I'll walk you through installing these extensions and discuss any interesting insights for doing so, and benefits of their enhancements (and some drawbacks). But you must use the extension links provided to make sure you download the latest stable versions of these extensions and follow the extension author's installation guides when installing these into your Joomla! site. If you run into any problems installing these extensions, please contact the extension's author for support. Always be sure to take the normal precaution of backing up your site before installation, at least for any non-stable extensions you may decide to try. Installing the Joomla! comment component Chances are, if you've invested in Joomla! 1.5 as your CMS, you need some powerful capabilities. Easy commenting with "captcha" images to reduce spam is always helpful: http://extensions.Joomla.org/extensions/contacts-&-feedback/comments/4389/details To install this extension (and the other few coming up), you have to basically go to Extensions | Install/Uninstall and upload the extension's ZIP file. You'll then proceed to the plugin, component, and/or modules panel and activate the extension so that it is ready to be implemented on your site. Upon installing this comment component, to my surprise, it told me that it was for an older version of Joomla! Everything on the download page seemed to indicate it worked with 1.5. The installation error did mention that I just needed to activate the System Legacy plugin and it would work. So I did, and the comment form appeared on all my article pages. This may seem like a step backward, but for extensions like this, which are very useful, if they work well and stay stable in Legacy Mode, a developer may have made the decision to leave well enough alone. The developer will most likely eventually upgrade the extension (especially if Legacy Mode goes away in future versions of Joomla!). Just be sure to sign up for updates or check back on any extensions you use if you do upgrade your site. You should do this regardless of whether your extensions run natively or in Legacy Mode. The advantage of AJAX in a comment form is that a user isn't distracted and comments post smoothly and right away (a bit of instant gratification for the user, even if you never "confirm" the post and it never gets actually published for other viewers). This extension outputs tables, but for the ease of handling robust comments and having a great admin area to manage them, I'll make do. The following screenshot shows the Joomla! comment component appearing in an article page: As you can see in my previous image, I have some strong styles that are trying to override the component's styles. A closer look at the output HTML will give me some class names and objects that I can target with CSS. The administration panel's Component | Joomla! Comment | Other Component settings page also allows quite a few customization options. The Layout tab also offers several included style sheets to select from as well as the option to copy the CSS sheet out to my template's directory (the component will do this automatically). This way, I can amend it with my own specific CSS, giving my comment form a better fit with my template's design. Installing the core design Ajax Pagebreak plugin If your site has long articles that get broken down regularly in to three or more pages, Pagebreak is a nice plugin that uses Ajax to smoothly load the next page. It's a useful feature that will also leave your site users with a little "oh wow" expression. http://www.greatJoomla.com/news/plugins/demo-core-design-ajaxpagebreak-plugin.html After successfully installing this plugin, I headed over to the Extensions | Plugin Manager and activated it. I then beefed out an article (with Lorem Ipsum) and added page breaks to it on the Home Page. It's hard to see in a screenshot, but it appears below the Prev and Next links without a full browser redraw. I've set my site up with SEO-friendly URLs, and this plugin does amend the URLs with a string; that is, http://yoururl.com/1.5dev/menu-item-4?start=1. I'm not sure how this will really affect the SEO "friendliness" value of my URL, but it does give me a specific URL to give to people if I want to send them to a targeted page, which is very good for accessibility. One thing to note, the first page of the article is the original URL; that is, http://yoururl.com/1.5dev/menu-item-4. The second page then appends ?start=1, the third page becomes ?start=2, and so on. Just be aware that when sending links out to people, it is always best to pull the URL directly from the site so that you know it's correct! Installing the AJAX RSS Reader Version 3 with Draggable Divs module RSS feeds are a great way to bring together a wide variety of content as well as bring all your or your organization's "social network happenings" to one place in your own site. I like to use RSS feeds to get people interested in knowing what an organization is doing (or tweeting), or reading, and so on. Having links and lists of what's currently going on can compel users to link to you, join your group, follow you, and become a friend, a fan, or whatever. This AJAX powered module has the extra feature of being draggable and somewhat editable. This is a nice way to draw a user in to the feeds and let them play with them and arrange the information to their taste. Sometimes, sorting and reorganizing makes you see connections and possibilities that you didn't see before. The next image may seem confusing, but it's a screenshot of the top div box being dragged and dropped: http://extensions.Joomla!.org/extensions/394/details AJAX: It's not just for your site's users I've already mentioned, when applied properly, how AJAX can aid in interface usability. Joomla! attempts to take advantage of this within its Administration panel by enhancing it with relevant information and compressing multiple page forms into one single screen area. Here's a quick look at how Joomla! already uses AJAX to enhance its Administration panel forms: The following image shows how the image uploader uses a "lightbox" div layer effect so that you can keep track of where you are in the content editor. In the next image, you can see how Joomla! helps keep the administration area cleared up by using smooth-sliding accordion panels. This helps you see everything on one page and have access to just what you need, when you need it.
Read more
  • 0
  • 0
  • 3125

article-image-agile-works-best-php-projects-2
Packt
30 Sep 2009
8 min read
Save for later

Agile Works Best in PHP Projects

Packt
30 Sep 2009
8 min read
What is agility Agility includes effective, that is, rapid and adaptive, response to change. This requires effective communication among all of the stakeholders. Stakeholders are those who are going to benefit from the project in some form or another. The key stakeholders of the project include the developers and the users. Leaders of the customer organization, as well as the leaders of the software development organizations, are also among the stakeholders. Rather than keeping the customer away, drawing the customer into the team helps the team to be more effective. There can be various types of customers, some are annoying, and some who tend to forget what they once said. There are also those who will help steer the project in the right direction. The idea of drawing the customer into the team is not to let them micromanage the team. Rather, it is for them to help the team to understand the user requirements better. This needs to be explained to the customers up front, if they seem to hinder the project, rather than trying to help in it. After all, it is the team that consists of the technical experts, so the customer should understand this. Organizing a team, in such a manner so that it is in control of the work performed, is also an important part of being able to adapt to change effectively. The team dynamics will help us to respond to changes in a short period of time without any major frictions. Agile processes are based on three key assumptions. These assumptions are as follows: It is difficult to predict in advance, which requirements or customer priorities will change and which will not. For many types of software, design and construction activities are interweaved. We can use construction to prove the design. Analysis, design, and testing are not as predictable from the planning's perspective as we software developers like them to be. To manage unpredictability, the agile process must be adapted incrementally by the project's team. Incremental adaptation requires customer's feedback. Based on the evaluation of delivered software, it increments or executes prototypes over short time periods. The length of the time periods should be selected based on the nature of the user requirements. It is ideal to restrict the length of a delivery to get incremented by two or three weeks. Agility yields rapid, incremental delivery of software. This makes sure that the client will get to see the real up-and-running software in quick time. Characteristics of an agile process An agile process is driven by the customer's demand. In other words, the process that is delivered is based on the users' descriptions of what is required. What the project's team builds is based on the user-given scenarios. The agile process also recognizes that plans are short lived. What is more important is to meet the users' requirements. Because the real world keeps on changing, plans have little meaning. Still, we cannot eliminate the need for planning. Constant planning will make sure that we will always be sensitive to where we're going, compared to where we are. Developing software iteratively, with a greater emphasis on construction activities, is another characteristic of the agile process. Construction activities make sure that we have something working all of the time. Activities such as requirements gathering for system modeling are not construction activities. Those activities, even though they're useful, do not deliver something tangible to the users. On the other hand, activities such as design, design prototyping, implementation, unit testing, and system testing are activities that deliver useful working software to the users. When our focus is on construction activities, it is a good practice that we deliver the software in multiple software increments. This gives us more time to incorporate user feedback, as we go deeper into implementing the product. This ensures that the team will deliver a high quality product at the end of the project's life cycle because the latter increments of software are based on clearly-understood requirements. This is as opposed to those, which would have been delivered with partially understood requirements in the earlier increments. As we go deep into the project's life cycle, we can adopt the project's team as well as the designs and the PHP code that we implement as changes occur. Principles of agility Our highest priority is to satisfy the customer through early and continuous delivery of useful and valuable software. To meet this requirement, we need to be able to embrace changes. We welcome changing requirements, even late in development life cycle. Agile processes leverage changes for the customer's competitive advantage. In order to attain and sustain competitive advantage over the competitors, the customer needs to be able to change the software system that he or she uses for the business at the customer's will. If the software is too rigid, there is no way that we can accommodate agility in the software that we develop. Therefore, not only the process, but also the product, needs to be equipped with agile characteristics. In addition, the customer will need to have new features of the software within a short period of time. This is required to beat the competitors with state of the art software system that facilitate latest business trends. Therefore, deliver the working software as soon as possible. A couple of weeks to a couple of months are always welcome. For example, the customer might want to improve the reports that are generated at the presentation layer based on the business data. Moreover, some of this business data will not have been captured in the data model in the initial design. Still, as the software development team, we need to be able to upgrade the design and implement the new set of reports using PHP in a very short period of time. We cannot afford to take months to improve the reports. Also, our process should be such that we will be able to accommodate this change and deliver it within a short period of time. In order to make sure that we can understand these types of changes, we need to make the business people and the developers daily work together throughout the project. When these two parties work together, it becomes very easy for them to understand each other. The team members are the most important resource in a software project. The motivation and attitude of these team members can be considered the most important aspect that will determine the success of the project. If we build the project around motivated individuals, give them the environment and support they need, trust them to get the job done, the project will be a definite success. Obviously, the individual team members need to work with each other in order to make the project a success. The most efficient and effective method of conveying information to and within a development team is a face-to-face conversation. Even though various electronic forms of communication, such as instant messaging, emails, and forums makes effective communication possible, there is nothing comparable to face-to-face communication. When it comes to evaluating progress, working software should be the primary measure of progress. We need to make sure that we clearly communicate this to all of the team members. They should always focus on making sure that the software they develop is in a working state at all times. It is not a bad idea to tie their performance reviews and evaluations based on how much effort they have put in. This is in order to make sure that whatever they deliver (software) is working all of the time. An agile process promotes sustainable development. This means that people are not overworked, and they are not under stress in any condition. The sponsors, managers, developers, and users should be able to maintain a constant pace of development, testing, evaluation, and evolution, indefinitely. The team should pay continuous attention to technical excellence. This is because good design enhances agility. Technical reviews with peers and non-technical reviews with users will allow corrective action to any deviations from the expected result. Aggressively seeking technical excellence will make sure that the team will be open minded and ready to adopt corrective action based on feedback. With PHP, simplicity is paramount. Simplicity should be used as the art of maximizing the amount of work that is not done. In other words, it is essential that we prevent unwanted wasteful work, as well as rework, at all costs. PHP is a very good vehicle to achieve this. The team members that we have should be smart and capable. If we can get those members to reflect on how to become more effective, at regular intervals, we can get the team to tune and adjust its behavior to enhance the process over time. The best architectures, requirements, and designs emerge from self-organizing teams. Therefore, for a high quality product, the formation of the team can have a direct impact.
Read more
  • 0
  • 0
  • 3124

article-image-developing-entity-metadata-wrappers
Packt
07 Aug 2013
8 min read
Save for later

Developing with Entity Metadata Wrappers

Packt
07 Aug 2013
8 min read
(For more resources related to this topic, see here.) Introducing entity metadata wrappers Entity metadata wrappers, or wrappers for brevity, are PHP wrapper classes for simplifying code that deals with entities. They abstract structure so that a developer can write code in a generic way when accessing entities and their properties. Wrappers also implement PHP iterator interfaces, making it easy to loop through all properties of an entity or all values of a multiple value property. The magic of wrappers is in their use of the following three classes: EntityStructureWrapper EntityListWrapper EntityValueWrapper The first has a subclass, EntityDrupalWrapper, and is the entity structure object that you'll deal with the most. Entity property values are either data, an array of values, or an array of entities. The EntityListWrapper class wraps an array of values or entities. As a result, generic code must inspect the value type before doing anything with a value, in order to prevent exceptions from being thrown. Creating an entity metadata wrapper object Let's take a look at two hypothetical entities that expose data from the following two database tables: ingredient recipe_ingredient The ingredient table has two fields: iid and name. The recipe_ingredient table has four fields: riid, iid , qty , and qty_unit. The schema would be as follows: Schema for ingredient and recipe_ingredient tables To load and wrap an ingredient entity with an iid of 1 and, we would use the following line of code: $wrapper = entity_metadata_wrapper('ingredient', 1); To load and wrap a recipe_ingredient entity with an riid of 1, we would use this line of code: $wrapper = entity_metadata_wrapper('recipe_ingredient', 1); Now that we have a wrapper, we can access the standard entity properties. Standard entity properties The first argument of the entity_metadata_wrapper function is the entity type, and the second argument is the entity identifier, which is the value of the entity's identifying property. Note, that it is not necessary to supply the bundle, as identifiers are properties of the entity type. When an entity is exposed to Drupal, the developer selects one of the database fields to be the entity's identifying property and another field to be the entity's label property. In our previous hypothetical example, a developer would declare iid as the identifying property and name as the label property of the ingredient entity. These two abstract properties, combined with the type property, are essential for making our code apply to multiple data structures that have different identifier fields. Notice how the phrase "type property" does not format the word "property"? That is not a typographical error. It is indicating to you that type is in fact the name of the property storing the entity's type. The other two, identifying property and label property are metadata in the entity declaration. The metadata is used by code to get the correct name for the properties on each entity in which the identifier and label are stored. To illustrate this, consider the following code snippet: $info = entity_get_info($entity_type);$key = isset($info['entity keys']['name']) ? $info['entity keys']['name'] : $info['entity keys']['id'];return isset($entity->$key) ? $entity->$key : NULL; Shown here is a snippet of the entity_id() function in the entity module. As you can see, the entity information is retrieved at the first highlight, then the identifying property name is retrieved from that information at the second highlight. That name is then used to retrieve the identifier from the entity. Note that it's possible to use a non-integer identifier, so remember to take that into account for any generic code. The label property can either be a database field name or a hook. The entity exposing developer can declare a hook that generates a label for their entity when the label is more complicated, such as what we would need for recipe_ingredient. For that, we would need to combine the qty, qty_unit, and the name properties of the referenced ingredient. Entity introspection In order to see the properties that an entity has, you can call the getPropertyInfo() method on the entity wrapper. This may save you time when debugging. You can have a look by sending it to devel module's dpm() function or var_dump: dpm($wrapper->getPropertyInfo());var_dump($wrapper->getPropertyInfo()); Using an entity metadata wrapper The standard operations for entities are CRUD: create, retrieve, update, and delete. Let's look at each of these operations in some example code. The code is part of the pde module's Drush file: sites/all/modules/pde/pde.drush.inc. Each CRUD operation is implemented in a Drush command, and the relevant code is given in the following subsections. Before each code example, there are two example command lines. The first shows you how to execute the Drush command for the operation. ; the second is the help command. Create Creation of entities is implemented in the drush_pde_entity_create function. Drush commands The following examples show the usage of the entity-create ( ec) Drush command and how to obtain help documentation for the command: $ drush ec ingredient '{"name": "Salt, pickling"}'$ drush help ec Code snippet $entity = entity_create($type, $data);// Can call $entity->save() here or wrap to play and save$wrapper = entity_metadata_wrapper($type, $entity);$wrapper->save(); In the highlighted lines we create an entity, wrap it, and then save it. The first line uses entity_create, to which we pass the entity type and an associative array having property names as keys and their values. The function returns an object that has Entity as its base class. The save() method does all the hard work of storing our entity in the database. No more calls to db_insert are needed! Whether you use the save() method on the wrapper or on the Entity object really depends on what you need to do before and after the save() method call. For example, if you need to plug values into fields before you save the entity, it's handy to use a wrapper. Retrieve The retrieving (reading) of entities is implemented in the drush_pde_print_entity() function. Drush commands The following examples show the usage of the entity-read (er) Drush command and how to obtain help documentation for the command. $ drush er ingredient 1$ drush help er Code snippet $header = ' Entity (' . $wrapper->type();$header .= ') - ID# '. $wrapper->getIdentifier().':';// equivalents: $wrapper->value()->entityType()// $wrapper->value()->identifier()$rows = array();foreach ($wrapper as $pkey => $property) { // $wrapper->$pkey === $property if (!($property instanceof EntityValueWrapper)) { $rows[$pkey] = $property->raw() . ' (' . $property->label() . ')'; } else { $rows[$pkey] = $property->value(); }} On the first highlighted line, we call the type() method of the wrapper, which returns the wrapped entity's type. The wrapped Entity object is returned by the value() method of the wrapper. Using wrappers gives us the wrapper benefits, and we can use the entity object directly! The second highlighted line calls the getIdentifier() method of the wrapper. This is the way in which you retrieve the entity's ID without knowing the identifying property name. We'll discuss more about the identifying property of an entity in a moment. Thanks to our wrapper object implementing the IteratorAggregate interface , we are able to use a foreach statement to iterate through all of the entity properties. Of course, it is also possible to access a single property by using its key. For example, to access the name property of our hypothetical ingredient entity, we would use $wrapper->name. The last three highlights are the raw(), label(), and value() method calls. The distinction between these is very important, and is as follows: raw(): This returns the property's value straight from the database. label(): This returns value of an entity's label property. For example, name. value(): This returns a property's wrapped data: either a value or another wrapper. Finally, the highlighted raw() and value() methods retrieve the property values for us. These methods are interchangeable when simple entities are used, as there's no difference between the storage value and property value. However, for complex properties such as dates, there is a difference. Therefore, as a rule of thumb, always use the value() method unless you absolutely need to retrieve the storage value. The example code is using the raw() method only so we that can explore it, and all remaining examples in this book will stick to the rule of thumb. I promise! Storage value: This is the value of a property in the underlying storage media. for example, database. Property value: This is the value of a property at the entity level after the value is converted from its storage value to something more pleasing. For example, date formatting of a Unix timestamp. Multi-valued properties need a quick mention here. Reading these is quite straightforward, as they are accessible as an array. You can use Array notation to get an element, and use a foreach to loop through them! The following is a hypothetical code snippet to illustrate this: $output = 'First property: ';$output .= $wrapper->property[0]->value();foreach ($wrapper->property as $vwrapper) { $output .= $vwrapper->value();} Summary This article delved into development using entity metadata wrappers for safe CRUD operations and entity introspection. Resources for Article: Further resources on this subject: Microsoft SQL Server 2008 R2 MDS: Creating and Using Models [Article] EJB 3 Entities [Article] ADO.NET Entity Framework [Article]
Read more
  • 0
  • 0
  • 3124

article-image-manage-sql-azure-databases-web-interface-houston
Packt
21 Jan 2011
2 min read
Save for later

Manage SQL Azure Databases with the Web Interface 'Houston'

Packt
21 Jan 2011
2 min read
  Microsoft SQL Azure Enterprise Application Development Build enterprise-ready applications and projects with SQL Azure Develop large scale enterprise applications using Microsoft SQL Azure Understand how to use the various third party programs such as DB Artisan, RedGate, ToadSoft etc developed for SQL Azure Master the exhaustive Data migration and Data Synchronization aspects of SQL Azure. Includes SQL Azure projects in incubation and more recent developments including all 2010 updates Appendix In order to use this program and follow the article you should have an account on the Windows Azure Platform on which preferably an SQL Azure server has been provisioned. This would also imply that you have a Windows Live ID to access the portal. As mentioned, in this article we look at some of the features of this web based tool and carry out a few tasks. Click the Launch Houston button in the Project Houston CTP1 page shown here on the SQLAzureLabs portal page. This brings up a world map displaying the current Windows Azure Data Centers available and you have to choose the data center on which you have an account. For the present article we will use the Southeast Asia data center and sometimes the North Central US data center. Click on Southeast Asia location. The Silverlight application gets launched from the URL: https://manage-sgp.cloudapp.net/ displaying the license information that you need to agree to before going forward. When you click OK, the Login in page is displayed as shown. You need to enter the server information at the Southeast Asia data center as shown. Click Connect. The connection gets established to the above SQL Azure server as shown in the next image. This is much better looking than the somewhat ‘drab’ looking SSMS interface (albeit fully mature)shown here for comparison. Changing the database If you need to work with a different database, click on Connect DB at the top left of 'Houston' user interface, as shown in the next image. The conneciton interface comes up again where you indicate the name of database as shown. Here the database has been changed to master. Click Connect now connects you to the master database as shown.
Read more
  • 0
  • 0
  • 3122

article-image-debugging-ajax-using-microsoft-ajax-library-internet-explorer-and-mozilla-firefox
Packt
22 Oct 2009
8 min read
Save for later

Debugging AJAX using Microsoft AJAX Library, Internet Explorer and Mozilla Firefox

Packt
22 Oct 2009
8 min read
AJAX Debugging Overview Unfortunately, today’s tools for client-side debugging and tracing aren’t as evolved as their server-side counterparts. For example, things such as capturing ongoing communication traffic between the client and the server, or client-side debugging, aren’t usually supported by today’s IDEs (Integrated Development Environments) such as Microsoft Visual Studio 2005. The next version of Visual Studio (code-named Orcas at the time of writing) promises a lot of improvements in this area: Improved IntelliSense technology with support for JavaScript code, which provides coding hints based on specially-formatted comments in the code Breakpoints in inline JavaScript code These are only the most important new coming features; there are others as well. For more information we suggest that you browse and keep an eye on Scott Guthrie’s blog at http://weblogs.asp.net/scottgu/, the JScript blog at http://blogs.msdn.com/jscript/, Bertrand Le Roy’s blog at http://weblogs.asp.net/bleroy/. Until this new edition of Visual Studio is released, we can rely on third-party tools that can do a very good job at helping us develop our AJAX applications. You’ll find a number of tools for Internet Explorer and Mozilla Firefox for this purpose. Debugging and Tracing with Microsoft AJAX Library The common practices for debugging JavaScript code are: Putting alert messages throughout the code to get notified about the values of the variables Logging tracing messages in a <div> element While the first option is straightforward, the second option offers a centralized place for storing different messages and could be considered more appropriate. Nevertheless both options can come in quite handy depending on the circumstances. Microsoft AJAX Library offers the Sys.Debug object that has a series of methods that you can use for debugging and tracing. The diagram of this class is presented in figure below. The Debug class As we can easily see in the diagram, Sys.Debug offers the most common features that we can find also in other languages: assert(), trace(), traceDump(), fail(), and clearTrace(). assert(), trace(), and fail() automatically send the messages to the debugging console of the browser. To see the messages in IE you need to have the Web Development Helper, and for Firefox you need the Firebug plugin. Both of these tools are presented later in this article. Internally assert() calls fail() if the expression evaluates to false. fail() simply logs the message passed in by assert to the debugging console. trace() offers an interesting feature beside logging to the debugging console: it offers the possibility to log the trace message in a <textarea> element with the ID TraceConsole. If such an element is found, trace() will log this message in this element too. The clearTrace() function simply clears the TraceConsole element, if found. The traceDump() function traces all the information about an object including its properties. Internally this function uses the trace() function so that we can have the information logged in the browser’s debugging console, and in the TraceConsole element (if it exists). MicrosoftAjax.debug.js You might have wondered why the Microsoft AJAX Library comes with both release and debug version of the JavaScript file. The major features of the debug version of the library files are:  The script is nicely formatted. The names of variables are not obfuscated. The script contains code comments. Some of the functions have the optional summary data that will be used by Visual Studio “Orcas” for code auto-completion. The script outputs debugging-friendly information. Parameters are validated. Once the development stage is finished, you can switch your application to the release version of the script (MicrosoftAjax.js), which is smaller and doesn’t contain the debugging features presented above. Perhaps the most interesting features of the debug version are the last two: debugging-friendly information and parameter validation. Anonymous Functions vs. Pseudo-Named Functions We will explain these two concepts by taking a look at how different functions are defined in the debug and release version of the library. The debug version of the library contains: function Sys$_Debug$assert(condition, message, displayCaller) {   ...}Sys._Debug.prototype = {  assert: Sys$_Debug$assert,  ...} and: String.format = function String$format(format, args) {...} In the release version of the library we have: Sys._Debug.prototype = {  assert: function(c, a, b) {  ...} and: String.format = function() {...} In the release version, we have methods that are anonymous functions. This means that within a debugger stack trace the method name will read JScript anonymous function. This is not very useful for debugging purposes, is it? Call Stack showing anonymous functions However, the debug version of the library uses the dollar-syntax to provide alias names for our functions: String$format for String.format and Sys$Debug$assert for Sys.Debug.assert. When using the debug version of the file, the stack trace would look like: Call Stack showing named functions We can still notice some anonymous functions as they are the result of creating callback or delegate functions. The example shows two different ways of coding:  In the debug version, the function is declared outside the prototype and then referenced in the prototype declaration. In the release version, the declaration is done directly where the function is declared (outside or inside the prototype). Parameters Validation Another interesting feature that has not been documented in the Microsoft AJAX Library documentation is that of parameters validation. Type safety is one of the typical problems when it comes to using JavaScript. Although the dynamic type features are really useful, sometimes we might really want to make sure that a parameter or object is of a certain type. To check the data type of an object, you can try converting the object to the desired type, or using the methods defined by Type. Fortunately the Microsoft AJAX Library has a function that does the dirty work for us: Function._validateParams(). The class diagram in figure below shows the _validateParameter() and _validateParams() methods of the Function class. The Function class The Function._validateParams() function, even if it is declared as private (by convention, using the leading underscore), can be used by our scripts as it is used throughout the debug version of the Microsoft AJAX Library. Here’s an example of using this function: function Sys$_Debug$fail(message) {/// <param name="message" type="String" mayBeNull="true"></param>   var e = Function._validateParams(arguments,          [ {name: "message", type: String, mayBeNull: true} ]);   if (e) throw e; This shows how the parameter for the fail() function is validated as a String. We can also see the additional code comments inside the function, which are meant to be used by the IntelliSense feature in Visual Studio “Orcas” to check for the correctness of the parameter types. While the first parameter of _validateParams() represents an array of parameters to be checked, the second parameter is an array of JSON objects describing the validation rules for the array of parameters. Each JSON object contains a validation rule for a parameter. The JSON object is a dictionary of keys and values. The list of keys that can be used is described in the table that follows. Key Description name The name of the parameter type The allowed type for this parameter (ex: String, Array, Function, Sys.Component, etc.) mayBeNull Boolean value indicating whether this parameter can be passed as null or not domElement Boolean value indicating whether this parameter is a DOM element or not integer Boolean value indicating whether this parameter should have an integer value or not optional Boolean value indicating whether this parameter is optional or not parameterArray Boolean value indicating whether this parameter should be an Array or not elementType The allowed type for each element of an array (type must be Array) elementMayBeNull Boolean value indicating whether an array element could have null or not (type must be Array) elementDomElement Boolean value indicating whether each element of an array is a DOM element (type must be Array) elementInteger Boolean value indicating whether each element of an array should have an integer value (type must be Array) The function returns an error message if the parameters don’t validate and the error is typically thrown like this: if (e) throw e; This exception could be caught and the appropriate measures taken programmatically. If the exception is not caught, the error will pop up in the debugging console of the browser.
Read more
  • 0
  • 0
  • 3121

article-image-error-handling-php-5-cms
Packt
17 Aug 2010
10 min read
Save for later

Error Handling in PHP 5 CMS

Packt
17 Aug 2010
10 min read
(For more resources on PHP, see here.) The problem Errors will happen whether we like it or not. Ideally the framework can help in their discovery, recording, and handling by: Trapping different kinds of errors Making a record of errors with sufficient detail to aid analysis Supporting a structure that mitigates the effect of errors Discussion There are three main kinds of errors that can arise. Many possible situations can crop up within PHP code that count as errors, such as an attempt to use a method on a variable that turns out not to be an object, or is an object but does not implement the specified method. The database will sometimes report errors, such as an attempt to retrieve information from a non-existent table, or to ask for a field that has not been defined for a table. And the logic of applications can often lead to situations that can only be described as errors. What resources do we have to handle these error situations? PHP error handling If nothing else is done, PHP has its own error handler. But developers are free to build their own handlers. So that is the first item on our to do list. Consistently with our generally object oriented approach, the natural thing to do is to build an error recording class, and then to tell PHP that one of its methods is to be called whenever PHP detects an error. Once that is done, the error handler must deal with whatever PHP passes, as it has taken over full responsibility for error handling. It has been a common practice to suppress the lowest levels of PHP error such as notices and warnings, but this is not really a good idea. Even these relatively unimportant messages can reveal more serious problems. It is not difficult to write code to avoid them, so that if a warning or notice does arise, it will indicate something unexpected and therefore worth investigation. For example, the PHP foreach statement expects to work on something iterable and will generate a warning if it is given, say, a null value. But this is easily avoided, either by making sure that methods which return arrays will always return an array, even if it is an array of zero items, rather than a null value. Failing that, the foreach can be protected by a preceding test. So it is safest to assume that a low level error may be a symptom of a bigger problem, and have our error handler record every error that is passed to it. The database is the obvious place to put the error, and the handler receives enough information to make it possible to save only the latest occurrence of the same error, thus avoiding a bloated table of many more or less identical errors. The other important mechanism offered by PHP is new to version 5 and is the try, catch, and throw construct. A section of code can be put within a try and followed by one or more catch specifications that define what is to be done if a particular kind of problem arises. The problems are triggered by using throw. This is a valuable mechanism for errors that need to break the flow of program execution, and is particularly helpful for dealing with database errors. It also has the advantage that the try sections can be nested, so if a large area of code, such as an entire component, is covered by a try it is still possible to write a try of narrower scope within that code. In general, it is better to be cautious about giving information about errors to users. For one thing, ordinary users are simply irritated by technically oriented error messages that mean nothing to them. Equally important is the issue of cracking, and the need to avoid displaying any weaknesses too clearly. It is bad enough that an error has occurred, without giving away details of what is going wrong. So a design assumption for error handling should be that the detail of errors is recorded for later analysis, but that only a very simple indication of the presence of an error is given to the user with a message that it has been noted for rectification. Database errors Errors in database operations are a particular problem for developers. Within the actual database handling code, it would be negligent to ignore the error indications that are available through the PHP interfaces to database systems. Yet within applications, it is hard to know what to do with such errors. SQL is very flexible, and a developer has no reason to expect any errors, so in the nature of things, any error that does arise is unexpected, and therefore difficult to handle. Furthermore, if there have to be several lines of error handling code every time the database is accessed, then the overhead in code size and loss of clarity is considerable. The best solution therefore seems to be to utilize the PHP try, catch, and throw structure. A special database error exception can be created by writing a suitable class, and the database handling code will then deal with an error situation by "throwing" a new error with an exception of that class. The CMS framework can have a default try and catch in place around most of its operation, so that individual applications within the CMS are not obliged to take any action. But if an application developer wants to handle database errors, it is always possible to do so by coding a nested try and catch within the application. One thing that must still be remembered by developers is that SQL easily allows some kinds of error situation to go unnoticed. For example, a DELETE or UPDATE SQL statement will not generate any error if nothing is deleted or updated. It is up to the developer to check how many rows, if any, were affected. This may not be worth doing, but issues of this kind need to be kept in mind when considering how software will work. A good error handling framework makes it easier for a developer to choose between different checking options. Application errors Even without there being a PHP or database error, an application may decide that an error situation has arisen. For some reason, normal processing is impossible, and the user cannot be expected to solve the problem. There are two main choices that will fit with the error handling framework we are considering. One is to use the PHP trigger_error statement. It raises a user error, and allows an error message to be specified. The error that is created will be trapped and passed to the error handler, since we have decided to have our own handler. This mechanism is best used for wholly unexpected errors that nonetheless could arise out of the logic of the application. The other choice is to use a complete try, catch, and throw structure within the application. This is most useful when there are a number of fatal errors that can arise, and are somewhat expected. The CMS extension installer uses this approach to deal with the various possible fatal errors that can occur during an attempt to install an extension. They are mostly related to errors in the XML packaging file, or in problems with accessing the file system. These are errors that need to be reported to help the user in resolving the problem, but they also involve abandoning the installation process. Whenever a situation of this kind arises, try, catch, and throw is a good way to deal with it. Exploring PHP—Error handling PHP provides quite a lot of control over error handling in its configuration. One question to be decided is whether to allow PHP to send any errors to the browser. This is determined by setting the value of display_errors in the php.ini configuration file. It is also possible to determine whether errors will be logged by setting log_errors and to decide where they should be logged by setting error_log. (Often there are several copies of this file, and it is important to find the one that is actually used by the system.) The case against sending errors is that it may give away information useful to crackers. Or it may look bad to users. On the other hand, it makes development and bug fixing harder if errors have to be looked up in a log file rather than being visible on the screen. And if errors are not sent to the screen, then in the event of a fatal error, the user will simply see a blank screen. This is not a good outcome either. Although the general advice is that errors should not be displayed on production systems, I am still rather inclined to show them. It seems to me that an error message, even if it is a technical one that is meaningless to the user, is rather better than a totally blank screen. The information given is only a bare description of the error, with the name and line number for the file having the error. It is unlikely to be a great deal of use to a cracker, especially since the PHP script just terminates on a fatal error, not leaving any clear opportunity for intrusion. You should make your own decision on which approach is preferable. Without any special action in the PHP code, an error will be reported by PHP giving details of where it occurred. Providing our own error handler by using the PHP set_error_handler function gives us far more flexibility to decide what information will be recorded and what will be shown to the user. A limitation on this is that PHP will still immediately terminate on a fatal error, such as attempting a method on something that is not an object. Termination also occurs whenever a parsing error is found, that is to say when the PHP program code is badly formed. It is not possible to have control transferred to a user provided error handler, which is an unfortunate limitation on what can be achieved. However, an error handler can take advantage of knowledge of the framework to capture relevant information. Quite apart from special information on the framework, the handler can make use of the useful PHP debug_backtrace function to find out the route that was followed before the error was reached. This will give information about what called the current code. It can then be used again to find what called that, and so on until no further trace information is available. A trace greatly increases the value of error reporting as it makes it much easier to find out the route that led to the error. When an error is trapped using PHP's try and catch, then it is best to trace the route to the error at the point the exception is thrown. Otherwise, the error trace will only show the chain of events from the exception to the error handler. There are a number of other PHP options that can further refine how errors are handled, but those just described form the primary tool box that we need for building a solid framework.
Read more
  • 0
  • 0
  • 3120
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-data-writing
Packt
23 Jan 2015
10 min read
Save for later

Data writing

Packt
23 Jan 2015
10 min read
In this article by P. Raja Malleswara Rao, author of the book Spring Batch Essentials, we will see how the Spring Batch provides the configuration to write the read and processed data to a different output (destination). The writer can integrate easily with different relational frameworks. It can also be customized for the different formats. (For more resources related to this topic, see here.) ItemWriter Spring Batch provides an interface in the form of ItemWriter to write bulk data.The following is the definition of the ItemWriter interface: public interface ItemWriter<T> { void write(List<? extends T> items) throws Exception; } Based on the destination platform onto which we have to write the data, we have the following item writers: Flat file item writers : These write the content onto a flat file (fixed width and delimited) XML item writers: These write the data onto an XML file Database item writers : These write the data onto a database Flat file item writers The data read from any of the existing formats can be processed to the desired format and then be written onto multiple formats, including flat files. The following are the APIs that help in flat file item writing. LineAggregator The LineAggregatorAPI concatenates multiple fields into a String to write onto the flat file. This works exactly the opposite way of LineTokenizer in the read operation. public interface LineAggregator<T> { public String aggregate(T item); } PassThroughLineAggregator PassThroughLineAggregator is an implementation of LineAggreagator that considers the object in use is already aggregated and simply returns the String from the object using the toString() method. public class PassThroughLineAggregator<T> implements LineAggregator<T> { public String aggregate(T item) { return item.toString(); } } The FlatFileItemWriter can be configured with the PassThroughLineAggregator, as follows: <bean id="itemWriter" class=" org.springframework.batch.item.file.FlatFileItemWriter"> <property name="resource" value="file:target/outputfiles/employee_output.txt"/> <property name="lineAggregator"> <bean class=" org.springframework.batch.item.file.transform.PassThroughLineAggregator"/> </property> </bean> FieldExtractor If the object writing is more than just writing its String form onto the file, FieldExtractor needs to be used, wherein each object gets converted to the array of fields, aggregated together to form a String to write onto the file. public interface FieldExtractor<T> { Object[] extract(T item); } Field extractors are primarily of two types: PassThroughFieldExtractor: For the scenario where the object collection has to just be converted to the array and passed to write BeanWrapperFieldExtractor: With a field-level configuration of how each field of the object gets placed in the String to write onto the file, this works exactly the opposite way of BeanWrapperFieldSetMapper The BeanWrapperFieldSetExtractor works as follows: BeanWrapperFieldExtractor<Employee> extractor = new BeanWrapperFieldExtractor<Employee>(); extractor.setEmployees(new String[] { "id", "lastname", "firstname","designation","department","yearofjoining"}); int id = 11; String lastname = "Alden"; String firstname = "Richie"; String desination = "associate"; String department = "sales"; int yearofjoining = 1996; Employee employee = new Employee(id, lastname, firstname,designation, department, yearofjoining); Object[] values = extractor.extract(n); assertEquals(id, values[0]); assertEquals(lastname, values[1]); assertEquals(firstname, values[2]); assertEquals(designation, values[3]); assertEquals(department, values[4]); assertEquals(yearofjoining, values[5]);/p> Writing delimited files If the Java object can be written onto the flat files in delimited file format, we can perform it as shown in the following example. Let's consider the Employee object defined already. This object can be configured with the FlatFileItemWriter, the DelimitedLineAggregator, and the BeanWrapperFieldExtractor to perform the delimited flat file, as follows: <bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"> <property name="resource" ref="outputResource"/> <property name="lineAggregator"> <bean class=" org.springframework.batch.item.file.transform.DelimitedLineAggregator"> <property name="delimiter" value=","/> <property name="fieldExtractor"> <bean class=" org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor"> <property name="employees" value="id,lastname,firstname,designation,department,yearofjoining"/> </bean> </property> </bean> </property> </bean> Writing a fixed width file Spring Batch supports fixed width file writing with the help of FormatterLineAggregator. Considering the same example data as delimited flat file writing, we can perform the fixed width file writing using the following configuration: <bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"> <property name="resource" ref="outputResource"/> <property name="lineAggregator"> <bean class=" org.springframework.batch.item.file.transform.FormatterLineAggregator"> <property name="fieldExtractor"> <bean class=" org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor"> <property name="employees" value=" id,lastname,firstname,designation,department,yearofjoining"/> </bean> </property> <property name="format" value="%-2d%-10s%-10s%-10s%-15s%-4d"/> </bean> </property> </bean> The format value is formed based on the following listed formatter conversions, where argrepresents the argument for conversion: Conversion Category Description b, B general This converts Boolean to the String format. The value is falsefor null h, H general This is the Integer.toHexString(arg.hashCode()) s, S general If argimplements Formattable, then arg.formatTo()Otherwise, arg.toString() c, C character This is a Unicode character d integral This is a decimal integer o integral This is an octal integer x, X integral This is a hexadecimal integer e, E floating point This is a decimal number in computerized scientific notation f floating point This is a decimal number g, G floating point This is a computerized scientific notation or decimal format, depending on the precision and value after rounding a, A floating point This is a hexadecimal floating point number with a significand and an exponent t, T date/time This is the prefix for date and time conversion characters % percent This is a literal %(u0025) n line separator This is the platform-specific line separator FlatFileItemWriter can be configured with the shouldDeleteIfExists option, to delete a file if it already exists in the specified location. The header and footer can be added to the flat file by implementing FlatFileHeaderCallBack and FlatFileFooterCallBack and including these beans with the headerCallback and footerCallback properties respectively. XML item writers The data can be written to the Extensible Markup Language (XML) format using StaxEventItemWriter. The Spring Batch configuration for this activity, for the employee example can be the following: <bean id="itemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter"> <property name="resource" ref="outputResource"/> <property name="marshaller" ref="employeeMarshaller"/> <property name="rootTagName" value="employees"/> <property name="overwriteOutput" value="true"/> </bean> Using the XStream to do the marshalling activity, the following is the configuration: <bean id="employeeMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> <property name="aliases"> <util:map id="aliases"> <entry key="employee" value="batch.Employee"/> <entry key="ID" value="java.lang.Integer"/> </util:map> </property> </bean> The Java code for the preceding configuration can be realized as follows: StaxEventItemWriter staxItemWriter = newStaxEventItemWriter(); FileSystemResource resource = new FileSystemResource("export/employee_output.xml") Map aliases = newHashMap(); aliases.put("employee","batch.Employee"); aliases.put("ID","java.lang.Integer"); Marshaller marshaller = newXStreamMarshaller(); marshaller.setAliases(aliases); staxItemWriter.setResource(resource); staxItemWriter.setMarshaller(marshaller); staxItemWriter.setRootTagName("employees"); staxItemWriter.setOverwriteOutput(true); ExecutionContext executionContext = newExecutionContext(); staxItemWriter.open(executionContext); Employee employee = new Employee(); employee.setID(11); employee.setLastName("Alden"); employee.setFirstName("Richie"); employee.setDesignation("associate"); employee.setDepartment("sales"); employee.setYearOfJoining("1996"); staxItemWriter.write(employee); Database item writers Spring Batch supports database item writing with two possible access types: JDBC and ORM. JDBC-based database writing Spring Batch supports JDBC-based database writing with the help of JdbcBatchItemWriter, which is an implementation of ItemWriter, which executes multiple SQL statements in the batch mode. The following is the sample configuration for the employee example with the JDBC-based database writing: <bean id="employeeWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter"> <property name="assertUpdates" value="true" /> <property name="itemPreparedStatementSetter"> <bean class="batch.EmployeePreparedStatementSetter" /> </property> <property name="sql" value="INSERT INTO EMPLOYEE (ID, LASTNAME, FIRSTNAME, DESIGNATION, DEPARTMENT, YEAROFJOINING) VALUES(?, ?, ?, ?, ?, ?)" /> <property name="dataSource" ref="dataSource" /> </bean> The ItemPreparedStatementSetter can be implemented for our example of Employee data as follows: public class EmployeePreparedStatementSetter implements ItemPreparedStatementSetter<Employee> { @Override public void setValues(Employee item, PreparedStatement ps) throws SQLException { ps.setInt(1, item.getId()); ps.setString(2, item.getLastName()); ps.setString(3, item.getFirstName()); ps.setString(4, item.getDesignation()); ps.setString(5, item.getDepartment()); ps.setInt(6, item.getYearOfJoining()); } } ORM-based database writing Object relational mapping(ORM) is defined as a programming technique to convert data between incompatible type systems in object-oriented programming languages. ORM takes care of the data persistence from the object oriented program to the database. Spring Batch supports multiple ORMs including Hibernate, JPA, and iBatis. In our example, the Employee class should be annotated to be used with ORM (Hibernate/JPA) for persistence as follows: @Entity("employee") public class Employee { @Id("id") private int id; @Column("lastName") private String lastName; @Column("firstName") private String firstName; @Column("designation") private String designation; @Column("department") private String department; @Column("yearOfJoining") private int yearOfJoining; public int getID() { return id; } public void setID(int id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public int getYearOfJoining() { return yearOfJoining; } public void setYearOfJoining(int yearOfJoining) { this.yearOfJoining = yearOfJoining; } } The annotations specify that the class Employee is representing a corresponding table in the database with a name as shown with @Entity, and each field corresponds to a column in the database as shown with the @ID and @Column annotations. The following is the configuration to be made with Hibernate for the employee example: <bean id="employeeWriter" class="org.springframework.batch.item.database.HibernateItemWriter"> <property name="hibernateTemplate" ref="hibernateTemplate" /> </bean> Similarly, for JPA and iBatis, the configurations can be made with JpaItemWriter and IbatisBatchItemWriter respectively. Custom item readers and writers Spring Batch supports custom item readers' and writers' configurations. This can be done easily by implementing the ItemReader and ItemWriter interfaces for the respective read and write operations with the business logic we want, and configuring the ItemReader and ItemWriter in the XML batch configuration. Summary Through this article we learned the essential data handling mechanism – writing the data to different destinations including flat files, XML, and databases. Now we have an understanding of the Spring Batch support that is used to custom formats by implementing the interface to match the business needs that are different from the default formats. Resources for Article:   Further resources on this subject: JAAS-based security authentication on JSPs [article] Serving and processing forms [article] Connecting to a web service (Should know) [article]
Read more
  • 0
  • 0
  • 3118

article-image-ejb-31-working-interceptors
Packt
06 Jul 2011
3 min read
Save for later

EJB 3.1: Working with Interceptors

Packt
06 Jul 2011
3 min read
EJB 3.1 Cookbook Build real world EJB solutions with a collection of simple but incredibly effective recipes with this book and eBook        The recipes in this article are based largely around a conference registration application as developed in the first recipe of the previous article on Introduction to Interceptors. It will be necessary to create this application before the other recipes in this article can be demonstrated. Using interceptors to enforce security While security is an important aspect of many applications, the use of programmatic security can clutter up business logic. The use of declarative annotations has come a long way in making security easier to use and less intrusive. However, there are still times when programmatic security is necessary. When it is, then the use of interceptors can help remove the security code from the business logic. Getting ready The process for using an interceptor to enforce security involves: Configuring and enabling security for the application server Adding a @DeclareRoles to the target class and the interceptor class Creating a security interceptor How to do it... Configure the application to handle security as detailed in Configuring the server to handle security recipe. Add the @DeclareRoles("employee") to the RegistrationManager class. Add a SecurityInterceptor class to the packt package. Inject a SessionContext object into the class. We will use this object to perform programmatic security. Also use the @DeclareRoles annotation. Next, add an interceptor method, verifyAccess, to the class. Use the SessionContext object and its isCallerInRole method to determine if the user is in the "employee" role. If so, invoke the proceed method and display a message to that effect. Otherwise, throw an EJBAccessException. @DeclareRoles("employee") public class SecurityInterceptor { @Resource private SessionContext sessionContext; @AroundInvoke public Object verifyAccess(InvocationContext context) throws Exception { System.out.println("SecurityInterceptor: Invoking method: " + context.getMethod().getName()); if (sessionContext.isCallerInRole("employee")) { Object result = context.proceed(); System.out.println("SecurityInterceptor: Returned from method: " + context.getMethod().getName()); return result; } else { throw new EJBAccessException(); } } } Execute the application. The user should be prompted for a username and password as shown in the following screenshot. Provide a user in the employee role. The application should execute to completion. Depending on the interceptors in place, you will console output similar to the following: INFO: Default Interceptor: Invoking method: register INFO: SimpleInterceptor entered: register INFO: SecurityInterceptor: Invoking method: register INFO: InternalMethod: Invoking method: register INFO: register INFO: Default Interceptor: Invoking method: create INFO: Default Interceptor: Returned from method: create INFO: InternalMethod: Returned from method: register INFO: SecurityInterceptor: Returned from method: register INFO: SimpleInterceptor exited: register INFO: Default Interceptor: Returned from method: register How it works... The @DeclareRoles annotation was used to specify that users in the employee role are associated with the class. The isCallerInRole method checked to see if the current user is in the employee role. When the target method is called, if the user is authorized then the InterceptorContext's proceed method is executed. If the user is not authorized, then the target method is not invoked and an exception is thrown. See also EJB 3.1: Controlling Security Programmatically Using JAAS  
Read more
  • 0
  • 0
  • 3118

article-image-exploring-adempiere-client-and-performing-tasks-part-1
Packt
08 Feb 2010
5 min read
Save for later

Exploring ADempiere Client and Performing Tasks: Part 1

Packt
08 Feb 2010
5 min read
At the start of a training session, a student from the class asks the following question: I have just installed ADempiere on my computer and launched the ADempiere Web Start client to log in to the application. However, I do not understand what to do with the application's screens. Even though I am already familiar with Microsoft Windows, the structure of these screens is quite new for me. Could you please explain these screens to me? This is not a naive question. Like all new users who do not have experience in operating ERP software applications, this student needs to know the purpose of the screen along with information on the buttons, tabs, and so on inside each screen. Once the users know the main function of a certain screen, they will use and operate the software more effectively. The Connection aspect of ADempiere Our pre-installed ADempiere application will contain a sample company data called GardenWorld company. To make ourselves familiar with ADempiere, we will access this company data, using a predefined user ID and password. Launch your ADempiere application server, and then launch the ADempiere Web Start client. Checking the ADempiere client version With ADempiere patches being frequently available, we need to know the version of ADempiere client that we are working on. In the ADempiere Web Start client/fat client (not web-based version), through the ADempiere Login window, you can find the information that indicates the version of ADempiere in use. In this window, you can find the ADempiere client version by examining the information in the format 3.4.2s+P20091109. With this information, the system tells you that you are using: The ADempiere 3.4.2s (stable) version The latest patches installed on the system released on November, 09 2009 The predefined user ID and password Coming to the ADempiere Login window, the system supplies us with a GardenAdmin User ID and an obscured Password. The question is: What exactly is the GardenAdmin password? Within your current connection window, the system will serve us with the GardenAdmin user ID. However, this is not the only user ID that is available. Our ADempiere installation has a common list of user IDs and passwords, as mentioned in the following table: No User ID Password 1 System System 2 SuperUser System 3 GardenAdmin GardenAdmin 4 GardenUser GardenUser We can try all of these user IDs in the Adempiere Login window. When typing these user IDs and passwords, check the Caps Lock status. The system will check the capitalization of the characters being typed. When supplied with a wrong password, you will get a User does not match password error message. After typing your GardenAdmin password, you will be directed to the Defaults tab of the Adempiere Login window. Here, you have an option to set the Role, Client, Organization, Warehouse, Date, and Printer values. Leave the information as it is, and click on the OK button. You are now playing with a preconfigured GardenWorld sample client. Understanding the Client and System users With the default ADempiere installation, we can group users into the following types: Client users System users The type of user is determined by the kind of Role being used when connecting to the ADempiere system. A Client user is a type of user who has the rights to access Client information (for example, GardenWorld Client), whereas a System user is a type of user who has the rights to perform system-related tasks, such as accessing and configuring the Application Dictionary through the System Client. With the Application Dictionary, you can perform low-level configuration, such as: Configure the Table and Column definitions to save your data Construct a Window, Tab, and fields to build your ADempiere window Set up a Report and Process to generate your reports Most of these parts can be done without altering the ADempiere source code. Any information in the Application Dictionary is user-extensible and can include user-specific configuration.   The GardenAdmin user ID is an example of a Client user. This user ID should be able to connect to the ADempiere server with the GardenWorld Admin or the GardenWorld User role. The System and SuperUser user IDs are examples of System users. When logging in to the ADempiere system, these IDs can connect with the System Administrator role.   SuperUser can be used to access both System and Client information. Changing our ADempiere server connection During our testing phase, it's quite common to have multiple ADempiere servers. At least, we will have both a demo and a production ADempiere application server environment. You can choose your target ADempiere server by clicking on the Server field on the Adempiere Login w indow, as shown in the following screenshot: During ADempiere installation, you will see an ADempiere Connection window. Complete the Application Host field with the target IP address (or computer name) of the ADempiere server, and leave the other fields with their default values. Ensure the connection between the client and the server computer by clicking on the Test Application Server button. If this button displays a green check mark, then the system will automatically put the information in the database connection information into this window. You can verify the database connection by clicking on the Test Database button. When both of these buttons display a green check mark, this means that we have successfully connected to both, the ADempiere server and the database server. Finalize this task by clicking on the OK button.
Read more
  • 0
  • 0
  • 3115

article-image-looking-apache-axis2
Packt
09 Oct 2009
11 min read
Save for later

Looking into Apache Axis2

Packt
09 Oct 2009
11 min read
(For more resources on Axis2, see here.) Axis2 Architecture Axis2 is built upon a modular architecture that consists of core modules and non-core modules. The core engine is said to be a pure SOAP processing engine (there is not any JAX-PRC concept burnt into the core). Every message coming into the system has to be transformed into a SOAP message before it is handed over to the core engine. An incoming message can either be a SOAP message or a non-SOAP message (REST JSON or JMX). But at the transport level, it will be converted into a SOAP message. When Axis2 was designed, the following key rules were incorporated into the architecture. These rules were mainly applied to achieve a highly flexible and extensible SOAP processing engine: Separation of logic and state to provide a stateless processing mechanism. (This is because Web Services are stateless.) A single information model in order to enable the system to suspend and resume. Ability to extend support to newer Web Service specifications with minimal changes made to the core architecture. The figure below shows all the key components in Axis2 architecture (including core components as well as non-core components). Core Modules XML Processing Model : Managing or processing the SOAP message is the most diffcult part of the execution of a message. The efficiency of message processing is the single most important factor that decides the performance of the entire system. Axis1 uses DOM as its message representation mechanism. However, Axis2 introduced a fresh XML InfoSet-based representation for SOAP messages. It is known as AXIOM (AXIs Object Model). AXIOM encapsulates the complexities of efficient XML processing within the implementation. SOAP Processing Model :  This model involves the processing of an incoming SOAP message. The model defines the different stages (phases) that the execution will walk through. The user can then extend the processing model in specific places. Information Model :  This keeps both static and dynamic states and has the logic to process them. The information model consists of two hierarchies to keep static and run-time information separate. Service life cycle and service session management are two objectives in the information model. Deployment Model :  The deployment model allows the user to easily deploy the services, configure the transports, and extend the SOAP Processing Model. It also introduces newer deployment mechanisms in order to handle hot deployment, hot updates, and J2EE-style deployment. Client API : This provides a convenient API for users to interact with Web Services using Axis2. The API consists of two sub-APIs, for average and advanced users. Axis2 default implementation supports all the eight MEPs (Message Exchange Patterns) defined in WSDL 2.0. The API also allows easy extension to support custom MEPs. Transports :  Axis2 defines a transport framework that allows the user to use and expose the same service in multiple transports. The transports fit into specific places in the SOAP processing model. The implementation, by default, provides a few common transports (HTTP, SMTP, JMX, TCP and so on). However, the user can write or plug-in custom transports, if needed. XML Processing Model Axis2 is built on a completely new architecture as compared to Axis 1.x. One of the key reasons for introducing Axis2 was to have a better, and an efficient XML processing model. Axis 1.x used DOM as its XML representation mechanism, which required the complete object hierarchy (corresponding to incoming message) to be kept in memory. This will not be a problem for a message of small size. But when it comes to a message of large size, it becomes an issue. To overcome this problem, Axis2 has introduced a new XML representation. AXIOM (AXIs Object Model) forms the basis of the XML representation for every SOAP-based message in Axis2. The advantage of AXIOM over other XML InfoSet representations is that it is based on the PULL parser technique, whereas most others are based on the PUSH parser technique. The main advantage of PULL over PUSH is that in the PULL technique, the invoker has full control over the parser and it can request the next event and act upon that, whereas in case of PUSH, the parser has limited control and delegates most of the functionality to handlers that respond to the events that are fired during its processing of the document. Since AXIOM is based on the PULL parser technique, it has on-demand-building capability whereby it will build an object model only if it is asked to do so. If required, one can directly access the underlying PULL parser from AXIOM, and use that rather than build an OM (Object Model). SOAP Processing Model Sending and receiving SOAP messages can be considered two of the key jobs of the SOAP-processing engine. The architecture in Axis2 provides two Pipes ('Flows'), in order to perform two basic actions. The AxisEngine or driver of Axis2 defines two methods, send() and receive() to implement these two Pipes. The two pipes are namedInFlow and OutFlow.   The complex Message Exchange Patterns (MEPs) are constructed by combining these two types of pipes. It should be noted that in addition to these two pipes there are two other pipes as well, and those two help in handling incoming Fault messages and sending a Fault message. Extensibility of the SOAP processing model is provided through handlers. When a SOAP message is being processed, the handlers that are registered will be executed. The handlers can be registered in global, service, or in operation scopes, and the final handler chain is calculated by combining the handlers from all the scopes. The handlers act as interceptors, and they process parts of the SOAP message and provide the quality of service features (a good example of quality of service is security or reliability). Usually handlers work on the SOAP headers; but they may access or change the SOAP body as well. The concept of a flow is very simple and it constitutes a series of phases wherein a phase refers to a collection of handlers. Depending on the MEP for a given method invocation, the number of flows associated with it may vary. In the case of an in-only MEP, the corresponding method invocation has only one pipe, that is, the message will only go through the in pipe (inflow). On the other hand, in the case of in-out MEP, the message will go through two pipes, that is the in pipe (inflow) and the out pipe (outflow). When a SOAP message is being sent, an OutFlow begins. The OutFlow invokes the handlers and ends with a Transport Sender that sends the SOAP message to the target endpoint. The SOAP message is received by a Transport Receiver at the target endpoint, which reads the SOAP message and starts the InFlow. The InFlow consists of handlers and ends with the Message Receiver, which handles the actual business logic invocation. A phase is a logical collection of one or more handlers, and sometimes a phase itself acts as a handler. Axis2 introduced the phase concept as an easy way of extending core functionalities. In Axis 1.x, we need to change the global configuration files if we want to add a handler into a handler chain. But Axis2 makes it easier by using the concept of phases and phase rules. Phase rules specify how a given set of handlers, inside a particular phase, are ordered. The figure below illustrates a flow and its phases. If the message has gone through the execution chain without having any problem, then the engine will hand over the message to the message receiver in order to do the business logic invocation, After this, it is up to the message receiver to invoke the service and send the response, if necessary. The figure below shows how the Message Receiver fits into the execution chain. The two pipes do not differentiate between the server and the client. The SOAP processing model handles the complexity and provides two abstract pipes to the user. The different areas or the stages of the pipes are named 'phases' in Axis2. A handler always runs inside a phase, and the phase provides a mechanism to specify the ordering of handlers. Both pipes have built-in phases, and both define the areas for User Phases, which can be defined by the user, as well. Information Model As  shown  in  the figure below, the information model consists of two hierarchies: Description hierarchy and Context hierarchy. The Description hierarchy represents the static data that may come from different deployment descriptors. If hot deployment is turned off, then the description hierarchy is not likely to change. If hot deployment is turned on, then we can deploy the service while the system is up and running. In this case, the description hierarchy is updated with the corresponding data of the service. The context hierarchy keeps run-time data. Unlike the description hierarchy, the context hierarchy keeps on changing when the server starts receiving messages. These two hierarchies create a model that provides the ability to search for key value pairs. When the values are to be searched for at a given level, they are searched while moving up the hierarchy until a match is found. In the resulting model, the lower levels override the values present in the upper levels. For example, when a value has been searched for in the Message Context and is not found, then it would be searched in the Operation Context, and so on. The search is first done up the hierarchy, and if the starting point is a Context then it would search for in the Description hierarchy as well. This allows the user to declare and override values, with the result being a very flexible configuration model. The flexibility could be the Achilles' heel of the system, as the search is expensive, especially for something that does not exist. Deployment Model The previous versions of Axis failed to address the usability factor involved in the deployment of a Web Service. This was due to the fact that Axis 1.x was released mainly to prove the Web Service concepts. Therefore in Axis 1.x, the user has to manually invoke the admin client and update the server classpath. Then, you need to restart the server in order to apply the changes. This burdensome deployment model was a definite barrier for beginners. Axis2 is engineered to overcome this drawback, and provide a flexible, user-friendly, easily configurable deployment model. Axis2 deployment introduced a J2EE-like deployment mechanism, wherein the developer can bundle all the class files, library files, resources files, and configuration fi  les together as an archive file, and drop it in a specified location in the file system. The concept of hot deployment and hot update is not a new technical paradigm, particularly for the Web Service platform. But in the case of Apache Axis, it is a new feature. Therefore, when Axis2 was developed, hot deployment features were added to the feature list. Hot deployment : This refers to the capability to deploy services while the system is up and running. In a real time system or in a business environment, the availability of the system is very important. If the processing of the system is slow, even for a moment, then the loss might be substantial and it may affect the viability of the business. In the meanwhile, it is required to add new service to the system. If this can be done without needing to shut down the servers, it will be a great achievement. Axis2 addresses this issue and provides a Web Service hot deployment ability, wherein we need not shut down the system to deploy a new Web Service. All that needs to be done is to drop the required Web Service archive into the services directory in the repository. The deployment model will automatically deploy the service and make it available. Hot update : This refers to the ability to make changes to an existing Web Service without even shutting down the system. This is an essential feature, which is best suited to use in a testing environment. It is not advisable to use hot updates in a real-time system, because a hot update could lead a system into an unknown state. Additionally, there is the possibility of loosening the existing service data of that service. To prevent this, Axis2 comes with the hot update parameter set to FALSE by default.
Read more
  • 0
  • 0
  • 3114
article-image-autoscaling-windows-azure-service-management-rest-api
Packt
08 Aug 2011
9 min read
Save for later

Autoscaling with the Windows Azure Service Management REST API

Packt
08 Aug 2011
9 min read
  Microsoft Windows Azure Development Cookbook A hosted service may have a predictable pattern such as heavy use during the week and limited use at the weekend. Alternatively, it may have an unpredictable pattern identifiable through various performance characteristics. Windows Azure charges by the hour for each compute instance, so the appropriate number of instances should be deployed at all times. The basic idea is that the number of instances for the various roles in the hosted service is modified to a value appropriate to a schedule or to the performance characteristics of the hosted service. We use the Service Management API to retrieve the service configuration for the hosted service, modify the instance count as appropriate, and then upload the service configuration. In this recipe, we will learn how to use the Windows Azure Service Management REST API to autoscale a hosted service depending on the day of the week. Getting ready We need to create a hosted service. We must create an X.509 certificate and upload it to the Windows Azure Portal twice: once as a management certificate and once as a service certificate to the hosted service. How to do it... We are going to vary the instance count of a web role deployed to the hosted service by using the Windows Azure Service Management REST API to modify the instance count in the service configuration. We are going to use two instances of the web role from Monday through Friday and one instance on Saturday and Sunday, where all days are calculated in UTC. We do this as follows: Create a Windows Azure Project and add an ASP.Net Web Role to it. Add the following using statements to the top of WebRole.cs: using System.Threading; using System.Xml.Linq; using System.Security.Cryptography.X509Certificates; Add the following members to the WebRole class in WebRole.cs: XNamespace wa = "http://schemas.microsoft.com/windowsazure"; XNamespace sc = http://schemas.microsoft.com/ ServiceHosting/2008/10/ServiceConfiguration"; String changeConfigurationFormat = https://management.core. windows.net/{0}/services/hostedservices/{1}/deploymentslots/{2}/ ?comp=config"; String getConfigurationFormat = https://management.core.windows. net/{0}/services/hostedservices/{1}/deploymentslots/{2}"; String subscriptionId = RoleEnvironment.GetConfigurationSettingVal ue("SubscriptionId"); String serviceName = RoleEnvironment.GetConfigurationSettingValue ("ServiceName"); String deploymentSlot = RoleEnvironment.GetConfigurationSettingVal ue("DeploymentSlot"); String thumbprint = RoleEnvironment.GetConfigurationSettingValue ("Thumbprint"); String roleName = "WebRole1"; String instanceId = "WebRole1_IN_0"; Add the following method, implementing RoleEntryPoint.Run(), to the WebRole class: WebRole class: public override void Run() { Int32 countMinutes = 0; while (true) { Thread.Sleep(60000); if (++countMinutes == 20) { countMinutes = 0; if ( RoleEnvironment.CurrentRoleInstance.Id == instanceId) { ChangeInstanceCount(); } } } } Add the following method, controlling the instance count change, to the WebRole class: private void ChangeInstanceCount() { XElement configuration = LoadConfiguration(); Int32 requiredInstanceCount = CalculateRequiredInstanceCount(); if (GetInstanceCount(configuration) != requiredInstanceCount) { SetInstanceCount(configuration, requiredInstanceCount); String requestId = SaveConfiguration(configuration); } } Add the following method, calculating the required instance count, to the WebRole class: private Int32 CalculateRequiredInstanceCount() { Int32 instanceCount = 2; DayOfWeek dayOfWeek = DateTime.UtcNow.DayOfWeek; if (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday) { instanceCount = 1; } return instanceCount; } Add the following method, retrieving the instance count from the service configuration, to the WebRole class: private Int32 GetInstanceCount(XElement configuration) { XElement instanceElement = (from s in configuration.Elements(sc + "Role") where s.Attribute("name").Value == roleName select s.Element(sc + "Instances")).First(); Int32 instanceCount = (Int32)Convert.ToInt32( instanceElement.Attribute("count").Value); return instanceCount; } Add the following method, setting the instance count in the service configuration, to the WebRole class: private void SetInstanceCount( XElement configuration, Int32 value) { XElement instanceElement = (from s in configuration.Elements(sc + "Role") where s.Attribute("name").Value == roleName select s.Element(sc + "Instances")).First(); instanceElement.SetAttributeValue("count", value); } Add the following method, creating the payload for the change deployment configuration operation, to the WebRole class: private XDocument CreatePayload(XElement configuration) { String configurationString = configuration.ToString(); String base64Configuration = ConvertToBase64String(configurationString); XElement xConfiguration = new XElement(wa + "Configuration", base64Configuration); XElement xChangeConfiguration = new XElement(wa + "ChangeConfiguration", xConfiguration); XDocument payload = new XDocument(); payload.Add(xChangeConfiguration); payload.Declaration = new XDeclaration("1.0", "UTF-8", "no"); return payload; } Add the following method, loading the service configuration, to the WebRole class: private XElement LoadConfiguration() { String uri = String.Format(getConfigurationFormat, subscriptionId, serviceName, deploymentSlot); ServiceManagementOperation operation = new ServiceManagementOperation(thumbprint); XDocument deployment = operation.Invoke(uri); String base64Configuration = deployment.Element( wa + "Deployment").Element(wa + "Configuration").Value; String stringConfiguration = ConvertFromBase64String(base64Configuration); XElement configuration = XElement.Parse(stringConfiguration); return configuration; } Add the following method, saving the service configuration, to the WebRole class: private String SaveConfiguration(XElement configuration) { String uri = String.Format(changeConfigurationFormat, subscriptionId, serviceName, deploymentSlot); XDocument payload = CreatePayload(configuration); ServiceManagementOperation operation = new ServiceManagementOperation(thumbprint); String requestId = operation.Invoke(uri, payload); return requestId; } Add the following utility methods, converting a String to and from its base-64 encoded version, to the WebRole class: private String ConvertToBase64String(String value) { Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value); String base64String = Convert.ToBase64String(bytes); return base64String; } private String ConvertFromBase64String(String base64Value) { Byte[] bytes = Convert.FromBase64String(base64Value); String value = System.Text.Encoding.UTF8.GetString(bytes); return value; } Add the ServiceManagementOperation class described in the Getting ready section of the Creating a Windows Azure hosted service recipe to the WebRole1 project. Set the ConfigurationSettings element in the ServiceDefinition.csdef file to: <ConfigurationSettings> <Setting name="DeploymentSlot" /> <Setting name="ServiceName" /> <Setting name="SubscriptionId" /> <Setting name="Thumbprint" /> </ConfigurationSettings> Set the ConfigurationSettings element in the ServiceDefinition.cscfg file to the following: <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics. ConnectionString" alue="DefaultEndpointsProtocol=https;AccountNam e=ACCOUNT_NAME;AccountKey=ACCOUNT_KEY" /> <Setting name="DeploymentSlot" value="production" /> <Setting name="ServiceName" value="SERVICE_NAME" /> <Setting name="SubscriptionId" value="SUBSCRIPTION_ID" /> <Setting name="Thumbprint" value="THUMBPRINT" /> </ConfigurationSettings> How it works... In steps 1 and 2, we set up the WebRole class. In step 3, we add private members to define the XML namespace used in processing the response and the String format used in generating the endpoint for the change deployment configuration and get deployment operations. We then initialize several values from configuration settings in the service configuration file deployed to each instance. In step 4, we implement the Run() class . Every 20 minutes, the thread this method runs in wakes up and, only in the instance named WebRole1_IN_0, invokes the method controlling the instance count for the web role. This code runs in a single instance to ensure that there is no race condition with multiple instances trying to change the instance count simultaneously. In step 5, we load the service configuration. If we detect that the instance count should change we modify the service configuration to have the desired instance count and then save the service configuration. Note that the service configuration used here is downloaded and uploaded using the Service Management API. Step 6 contains the code where we calculate the needed instance count. In this example, we choose an instance count of 2 from Monday through Friday and 1 on Saturday and Sunday. All days are specified in UTC. This is the step where we should insert the desired scaling algorithm. In step 7, we retrieve the instance count for the web role from the service configuration. In step 8, we set the instance count to the desired value in the service configuration. In step 9, we create the payload for the change deployment configuration operation. We create a Configuration element and add a base-64 encoded copy of the service configuration to it. We add the Configuration element to the root ChangeConfiguration element which we then add to an XML document. In step 10, we use the ServiceManagementOperation utility class , described in the Creating a Windows Azure hosted service recipe, to invoke the get deployment operation on the Service Management API. The Invoke() method creates an HttpWebRequest, adds the required X.509 certificate, and sends the request to the get deployment endpoint. We load the response into an XML document from which we extract the base-64 encoded service configuration. We then convert this into its XML format and load this into an XElement which we return. In step 11, we use the ServiceManagementOperation utility class to invoke the change deployment configuration operation on the Service Management API. The Invoke() method creates an HttpWebRequest, adds the required X.509 certificate and the payload, and then sends the request to the change deployment configuration endpoint. It then parses the response to retrieve the request ID. In step 12, we add two utility methods to convert to and from a base-64 encoded String. In step 13, we add the ServiceManagementOperation utility class that we use to invoke operations against the Service Management API. In steps 14 and 15, we define some configuration settings in the service definition file and specify them in the service configuration file. We provide values for the Windows Azure Storage Service account name and access key. We also provide the subscription ID for the Windows Azure subscription, as well as the service name for current hosted service. We also need to add the thumbprint for the X.509 certificate we uploaded as a management certificate to the Windows Azure subscription and a service certificate to the hosted service we are deploying this application into. Note that this thumbprint is the same as that configured in the Certificate section of the ServiceConfiguration.cscfg file. This duplication is necessary because the Certificate section of this file is not accessible to the application code. Summary Windows Azure charges by the hour for each compute instance, so the appropriate number of instances should be deployed at all times. Autoscaling with the Windows Azure Service Management REST API as shown in this article is a boon in terms of keeping track of number of deployments at any time. Further resources on this subject: Managing Azure Hosted Services with the Service Management API [Article] Using the Windows Azure Platform PowerShell Cmdlets [Article] Windows Azure Diagnostics: Initializing the Configuration and Using a Configuration File [Article] Digging into Windows Azure Diagnostics [Article] Using IntelliTrace to Diagnose Problems with a Hosted Service [Article]
Read more
  • 0
  • 0
  • 3111

article-image-vmware-vrealize-operations-performance-and-capacity-management
Packt
08 May 2015
4 min read
Save for later

VMware vRealize Operations Performance and Capacity Management

Packt
08 May 2015
4 min read
Virtualization is what allows companies like Dropbox and Spotify to operate internationally with ever-growing customer bases. From virtualizing desktops, applications, and operating systems to creating highly-available platforms that enable developers to quickly host operating systems and entire content delivery networks, this book centers on the tools, techniques, and platforms that administrators and developers use to decouple and utilize hardware and infrastructure resources to power applications and web services. Key pointers vCenter, vSphere, VMware, VM, Virtualization, SDDC Counters, key counters, metric groups, vRealize, ESXi Cluster, Datastore, Datastore Cluster, Datacenter CPU, Network, Disk, Storage, Contention, Utilization, Memory vSwitch, vMotion, Capacity Management, Performance Management, Dashboards, vC Ops What the book covers Content-wise, the book is split into two main parts. The first part provides the foundation and theory. The second part provides the solutions and sample use cases. It aims to clear up the misunderstandings that customers have about SDDC. It explains why a VM is radically different from a physical server, and hence a virtual data center is fundamentally different from a physical data center. It then covers the aspects of management that are affected. It also covers the practical aspects of this book, as they show how sample solutions are implemented. The chapters in the book provide both performance management and capacity management. How the book differs Virtualization is one of the biggest shifts in IT history. Almost all large enterprises are embarking on a journey to transform the IT department into a service provider. VMware vRealize Operations Management is a suite of products that automates operations management using patented analytics and an integrated approach to performance, capacity, and configuration management. vCenter Operations Manager is the most important component of this suite that helps Administrators to maintain and troubleshoot your VMware environment as well as your physical environment. Written in a light and easy-to-follow language, the book differs in a way as it covers the complex topic of managing performance and capacity when the datacentre is software defined. It sets the foundation by demystifying deep rooted misunderstanding on virtualization and virtual machine. How will the book help you Master the not-so-obvious differences between a physical server and a virtual machine that customers struggle with during management of virtual datacentre Educate and convince your peers on why and how performance and capacity management change in virtual datacentre Correct many misperceptions about virtualization Know how your peers operationalize their vRealize Operations Master all the key metrics in vSphere and vRealize Operations Be confident in performance troubleshooting with vSphere and vRealize Operations See real-life examples of how super metric and advance dashboards make management easier Develop rich, custom dashboards with interaction and super metrics Unlearn the knowledge that makes performance and capacity management difficult in SDDC Master the counters in vCenter and vRealize Operations by knowing what they mean and their interdependencies Build rich dashboards using a practical and easy-to-follow approach supported with real-life examples Summary The book would teach how to get the best out of vCenter Operations in managing performance and capacity in a Software-Defined datacenter. The book starts by explaining the difference between a Software-Defined datacentre and classic physical datacentre, and how it impacts both architecture and operations. From this strategic view, the book then zooms into the most common challenge, which is performance management. The book then covers all the key counters in both vSphere and vRealize Operations, explains their dependency, and provides practical guidance on values you should expect in a healthy environment. At the end, the book puts the theory together and provides real-life examples created together with customers. This book is an invaluable resource for those embarking on a journey to master Virtualization. Resources for Article: Further resources on this subject: Backups in the VMware View Infrastructure [Article] VMware vCenter Operations Manager Essentials - Introduction to vCenter Operations Manager [Article] An Introduction to VMware Horizon Mirage [Article]
Read more
  • 0
  • 0
  • 3110

article-image-creating-our-first-animation-angularjs
Packt
31 Oct 2014
36 min read
Save for later

Creating Our First Animation in AngularJS

Packt
31 Oct 2014
36 min read
In this article by Richard Keller, author of the book Learning AngularJS Animations, we will learn how to apply CSS animations within the context of AngularJS by creating animations using CSS transitions and CSS keyframe animations that are integrated with AngularJS native directives using the ngAnimate module. In this article, we will learn: The ngAnimate module setup and usage AngularJS directives with support for out-of-the-box animation AngularJS animations with the CSS transition AngularJS animations with CSS keyframe animations The naming convention of the CSS animation classes Animation of the ngMessage and ngMessages directives (For more resources related to this topic, see here.) The ngAnimate module setup and usage AngularJS is a module-based framework; if we want our AngularJS application to have the animation feature, we need to add the animation module (ngAnimate). We have to include this module in the application by adding the module as a dependency in our AngularJS application. However, before that, we should include the JavaScript angular-animate.js file in HTML. Both files are available on the Google content distribution network (CDN), Bower, Google Code, and https://angularjs.org/. The Google developers' CDN hosts many versions of AngularJS, as listed here: https://developers.google.com/speed/libraries/devguide#angularjs Currently, AngularJS Version 1.3 is the latest stable version, so we will use AngularJS Version 1.3.0 on all samples files of this book; we can get them from https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js and https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular-animate.min.js. You might want to use Bower. To do so, check out this great video article at https://thinkster.io/egghead/intro-to-bower/, explaining how to use Bower to get AngularJS. We include the JavaScript files of AngularJS and the ngAnimate module, and then we include the ngAnimate module as a dependency of our app. This is shown in the following sample, using the Google CDN and the minified versions of both files: <!DOCTYPE html> <html ng-app"myApp"> <head> <title>AngularJS animation installation</title> </head> <body> <script src="//ajax.googleapis.com/ajax/libs/angularjs/    1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/    1.3.0/angular-animate.min.js"></script> <script>    var app = angular.module('myApp', ['ngAnimate']); </script> </body> </html> Here, we already have an AngularJS web app configured to use animations. Now, we will learn how to animate using AngularJS directives. AngularJS directives with native support for animations AngularJS has the purpose of changing the way web developers and designers manipulate the Document Object Model (DOM). We don't directly manipulate the DOM when developing controllers, services, and templates. AngularJS does all the DOM manipulation work for us. The only place where an application touches the DOM is within directives. For most of the DOM manipulation requirements, AngularJS already provides are built-in directives that fit our needs. There are many important AngularJS directives that already have built-in support for animations, and they use the ngAnimate module. This is why this module is so useful; it allows us to use animations within AngularJS directives DOM manipulation. This way, we don't have to replicate native directives by extending them just to add animation functionality. The ngAnimate module provides us a way to hook animations in between AngularJS directives execution. It even allows us to hook on custom directives. As we are dealing with animations between DOM manipulations, we can have animations before and after an element is added to or removed from the DOM, after an element changes (by adding or removing classes), and before and after an element is moved in the DOM. These events are the moments when we might add animations. Fade animations using AngularJS Now that we already know how to install a web app with the ngAnimate module enabled, let's create fade-in and fade-out animations to get started with AngularJS animations. We will use the same HTML from the installation topic and add a simple controller, just to change an ngShow directive model value and add a CSS transition. The ngShow directive shows or hides the given element based on the expression provided to the ng-show attribute. For this sample, we have a Toggle fade button that changes the ngShow model value, so we can see what happens when the element fades in and fades out from the DOM. The ngShow directive shows and hides an element by adding and removing the ng-hide class from the element that contains the directive, shown as follows: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS animation installation</title> </head> <body> <style type="text/css">    .firstSampleAnimation.ng-hide-add,    .firstSampleAnimation.ng-hide-remove {     -webkit-transition: 1s ease-in-out opacity;     transition: 1s ease-in-out opacity;     opacity: 1;  } .firstSampleAnimation.ng-hide { opacity: 0; } </style> <div> <div ng-controller="animationsCtrl"> <h1>ngShow animation</h1> <button ng-click="fadeAnimation = !fadeAnimation">Toggle fade</button> fadeAnimation value: {{fadeAnimation}} <div class="firstSampleAnimation" ng-show="fadeAnimation"> This element appears when the fadeAnimation model is true </div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs/ 1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs/ 1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); app.controller('animationsCtrl', function ($scope) { $scope.fadeAnimation = false; }); </script> </body> </html> In the CSS code, we declared an opacity transition to elements with the firstAnimationSample and ng-hide-add classes, or elements with the firstAnimationSample and ng-hide-remove classes. We also added the firstAnimationSample class to the same element that has the ng-show directive attribute. The fadeAnimation model is initially false, so the element with the ngShow directive is initially hidden, as the ngShow directive adds the ng-hide class to the element to set the display property as none. When we first click on the Toggle fade button, the fadeAnimation model will become true. Then, the ngShow directive will remove the ng-hide class to display the element. But before that, the ngAnimate module knows there is a transition declared for this element. Because of that, the ngAnimate module will append the ng-hide-remove class to trigger the hide animation start. Then, ngAnimate will add the ng-hide-remove-active class that can contain the final state of the animation to the element and remove the ng-hide class at the same time. Both classes will last until the animation (1 second in this sample) finishes, and then they are removed. This is the fade-in animation; ngAnimate triggers animations by adding and removing the classes that contain the animations; this is why we say that AngularJS animations are class based. This is where the magic happens. All that we did to create this fade-in animation was declare a CSS transition with the class name, ng-hide-remove. This class name means that it's appended when the ng-hide class is removed. The fade-out animation will happen when we click on the Toggle fade button again, and then, the fadeAnimation model will become false. The ngShow directive will add the ng-hide class to remove the element, but before this, the ngAnimate module knows that there is a transition declared for that element too. The ngAnimate module will append the ng-hide-add class and then add the ng-hide and ng-hide-add-active classes to the element at the same time. Both classes will last until the animation (1 second in this sample) finishes, then they are removed, and only the ng-hide class is kept, to hide the element. The fade-out animation was created by just declaring the CSS transition with the class name of ng-hide-add. It is easy to understand that this class is appended to the element when the ng-hide class is about to be added. The AngularJS animations convention As this article is intended to teach you how to create animations with AngularJS, you need to know which directives already have built-in support for AngularJS animations to make our life easier. Here, we have a table of directives with the directive names and the events of the directive life cycle when animation hooks are supported. The first row means that the ngRepeat directive supports animation on enter, leave, and move event times. All events are relative to DOM manipulations, for example, when an element enters or leaves DOM, or when a class is added to or removed from an element. Directive Supported animations ngRepeat Enter, leave, and move ngView Enter and leave ngInclude Enter and leave ngSwitch Enter and leave ngIf Enter and leave ngClass Add and remove ngShow and ngHide Add and remove form and ngModel Add and remove ngMessages Add and remove ngMessage Enter and leave Perhaps, the more experienced AngularJS users have noticed that the most frequently used directives are attended in this list. This is great; it means that animating with AngularJS isn't hard for most use cases. AngularJS animation with CSS transitions We need to know how to bind the CSS animation as well as the AngularJS directives listed in the previous table. The ngIf directive, for example, has support for the enter and leave animations. When the value of the ngIf model is changed to true, it triggers the animation by adding the ng-enter class to the element just after the ngIf DOM element is created and injected. This triggers the animation, and the classes are kept for the duration of the transition ends. Then, the ng-enter class is removed. When the value of ngIf is changed to false, the ng-leave class is added to the element just before the ngIf content is removed from the DOM, and so, the animation is triggered while the element still exists. To illustrate the AngularJS ngIf directive and ngAnimate module behavior, let's see what happens in a sample. First, we have to declare a button that toggles the value of the fadeAnimation model, and one div tag that uses ng-if="fadeAnimation", so we can see what happens when the element is removed and added back. Here, we create the HTML code using the HTML template we used in the last topic to install the ngAnimate module: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngIf sample</title> </head> <body> <style> /* ngIf animation */ .animationIf.ng-enter, .animationIf.ng-leave { -webkit-transition: opacity ease-in-out 1s; transition: opacity ease-in-out 1s; } .animationIf.ng-enter, .animationIf.ng-leave.ng-leave-active { opacity: 0; } .animationIf.ng-leave, .animationIf.ng-enter.ng-enter-active { opacity: 1; } </style> <div ng-controller="animationsCtrl"> <h1>ngIf animation</h1> <div> fadeAnimation value: {{fadeAnimation}} </div> <button ng-click="fadeAnimation = !fadeAnimation"> Toggle fade</button> <div ng-if="fadeAnimation" class="animationIf"> This element appears when the fadeAnimation model is true </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); app.controller('animationsCtrl', function ($scope) { $scope.fadeAnimation = false; }); </script> </body> </html> So, let's see what happens in the DOM just after we click on the Toggle fade button. We will use Chrome Developer Tools (Chrome DevTools) to check the HTML in each animation step. It's a native tool that comes with the Chrome browser. To open Chrome DevTools, you just need to right-click on any part of the page and click on Inspect Element. The ng-enter class Our CSS declaration added an animation to the element with the animationIf and ng-enter classes. So, the transition is applied when the element has the ng-enter class too. This class is appended to the element when the element has just entered the DOM. It's important to add the specific class of the element you want to animate in the selector, which in this case is the animationIf class, because many other elements might trigger animation and add the ng-enter class too. We should be careful to use the specific target element class. Until the animation is completed, the resulting HTML fragment will be as follows: Consider the following snippet: <div ng-if="fadeAnimation" class="animationIf ng-scope ng-animate ng-enter ng-enter-active"> fadeAnimation value: true </div> We can see that the ng-animate, ng-enter, and ng-enter-active classes were added to the element. After the animation is completed, the DOM will have the animation classes removed as the next screenshot shows: As you can see, the animation classes are removed: <div ng-if="fadeAnimation" class="animationIf ng-scope"> This element appears when the fadeAnimation model is true </div> The ng-leave class We added the same transition of the ng-enter class to the element with the animationIf and ng-leave classes. The ng-leave class is added to the element before the element leaves the DOM. So, before the element vanishes, it will display the fade effect too. If we click again on the Toggle fade button, the leave animation will be displayed and the following HTML fragment and screen will be rendered: The fragment rendered is as follows: <div ng-if="fadeAnimation" class="animationIf ng-scope g-animate ng-leave ng-leave-active"> This element appears when the fadeAnimation model is true </div> We can notice that the ng-animate, ng-leave, and ng-leave-active classes were added to the element. Finally, after the element is removed from the DOM, the rendered result will be as follows: The code after removing the element is as follows: <div ng-controller="animationsCtrl" class="ng-scope"> <div class="ng-binding"> fadeAnimation value: false </div> <button ng-click="fadeAnimation = !fadeAnimation"> Toggle fade</button> <!-- ngIf: fadeAnimation --> </div> Furthermore, there are the ng-enter-active and ng-leave-active classes. They are appended to the element classes too. Both are used to define the target value of the transition, and the -active classes define the destination CSS so that we can create a transition between the start and the end of an event. For example, ng-enter is the initial class of the enter event and ng-enter-active is the final class of the enter event. They are used to determine the style applied at the start of the animation beginning and the final transition style, and they are displayed when the transition completes the cycle. A use case of the -active class is when we want to set an initial color and a final color using the CSS transition. In the last sample case, the ng-leave class has opacity set to 1 and the ng-leave-active class has the opacity set to 0; so, the element will fade away at the end of the animation. Great, we just created our first animation using AngularJS and CSS transitions. AngularJS animation with CSS keyframe animations We created an animation using the ngIf directive and CSS transitions. Now we are going to create an animation using ngRepeat and CSS animations (keyframes). As we saw in the earlier table on directives and the supported animation events, the ngRepeat directive supports animation on the enter, leave, and move events. We already used the enter and leave events in the last sample. The move event is triggered when an item is moved around on the list of items. For this sample, we will create three functions on the controller scope: one to add elements to the list in order to execute the enter event, one to remove an item from list in order to execute the leave event, and one to sort the elements so that we can see the move event. Here is the JavaScript with the functions; $scope.items is the array that we will use on the ngRepeat directive: var app = angular.module('myApp', ['ngAnimate']); app.controller('animationsCtrl', function ($scope) { $scope.items = [{ name: 'Richard' }, { name: 'Bruno' } , { name: 'Jobson' }]; $scope.counter = 0; $scope.addItem = function () { var name = 'Item' + $scope.counter++; $scope.items.push({ name: name }); }; $scope.removeItem = function () { var length = $scope.items.length; var indexRemoved = Math.floor(Math.random() * length); $scope.items.splice(indexRemoved, 1); }; $scope.sortItems = function () { $scope.items.sort(function (a, b) { return a[name] < b[name] ? -1 : 1 }); }; }); The HTML is as follows; it is without the CSS styles because we will see them later separating each animation block: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngRepeat sample</title> </head> <body> <div ng-controller="animationsCtrl"> <h1>ngRepeat Animation</h1> <div> <div ng-repeat="item in items" class="repeatItem"> {{item.name}} </div> <button ng-click="addItem()">Add item</button> <button ng-click="removeItem()">Remove item</button><button ng-click="sortItems()"> Sort items</button> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> </body> </html> We will add an animation to the element with the repeatItem and ng-enter classes, and we will declare the from and to keyframes. So, when an element appears, it starts with opacity set to 0 and color set as red and will animate for 1 second until opacity is 1 and color is black. This will be seen when an item is added to the ngRepeat array. The enter animation definition is declared as follows: /* ngRepeat ng-enter animation */ .repeatItem.ng-enter { -webkit-animation: 1s ng-enter-repeat-animation; animation: 1s ng-enter-repeat-animation; } @-webkit-keyframes ng-enter-repeat-animation { from { opacity: 0; color: red; } to { opacity: 1; color: black; } } @keyframes ng-enter-repeat-animation { from { opacity: 0; color: red; } to { opacity: 1; color: black; } } The move animation is declared next is to be triggered when we move an item of ngRepeat. We will add a keyframe animation to the element with the repeatItem and ng-move classes. We will declare the from and to keyframes. So, when an element moves, it starts with opacity set to 0 and color set as black and will animate for 1 second until opacity is 0.5 and color is blue, shown as follows: /* ngRepeat ng-move animation */ .repeatItem.ng-move { -webkit-animation: 1s ng-move-repeat-animation; animation: 1s ng-move-repeat-animation; } @-webkit-keyframes ng-move-repeat-animation { from { opacity: 1; color: black; } to { opacity: 0.5; color: blue; } } @keyframes ng-move-repeat-animation { from { opacity: 1; color: black; } to { opacity: 0.5; color: blue; } } The leave animation is declared next and is to be triggered when we remove an item of ngRepeat. We will add a keyframe animation to the element with the repeatItem and ng-leave classes; we will declare the from and to keyframes; so, when an element leaves the DOM, it starts with opacity set to 1 and color set as black and animates for 1 second until opacity is 0 and color is red, shown as follows: /* ngRepeat ng-leave animation */ .repeatItem.ng-leave { -webkit-animation: 1s ng-leave-repeat-animation; animation: 1s ng-leave-repeat-animation; } @-webkit-keyframes ng-leave-repeat-animation { from { opacity: 1; color: black; } to { opacity: 0; color: red; } } @keyframes ng-leave-repeat-animation { from { opacity: 1; color: black; } to { opacity: 0; color: red; } } We can see that the ng-enter-active and ng-leave-active classes aren't used on this sample, as the keyframe animation already determines the initial and final properties' states. In this case, as we used CSS keyframes, the classes with the -active suffix are useless, although for CSS transitions, it's useful to set an animation destination. The CSS naming convention In the last few sections, we saw how to create animations using AngularJS, CSS transitions, and CSS keyframe animations. Creating animations using both CSS transitions and CSS animations is very similar because all animations in AngularJS are class based, and AngularJS animations have a well-defined class name pattern. We must follow the CSS naming convention by adding a specific class to the directive element so that we can determine the element animation. Otherwise, the ngAnimate module will not be able to recognize which element the animation applies to. We already know that both ngIf and ngRepeat use the ng-enter, ng-enter-active, ng-leave, and ng-leave-active classes that are added to the element in the enter and leave events. It's the same naming convention used by the ngInclude, ngSwitch, ngMessage, and ngView directives. The ngHide and ngShow directives follow a different convention. They add the ng-hide-add and ng-hide-add-active classes when the element is going to be hidden. When the element is going to be shown, they add the ng-hide-remove and ng-hide-remove-active classes. These class names are more intuitive for the purpose of hiding and showing elements. There is also the ngClass directive convention that uses the class name added to create the animation classes with the -add, -add-active, -remove, and -remove-active suffixes, similar to the ngHide directive. The ngRepeat directive uses the ng-move and ng-move-active classes when elements move their position in the DOM, as we already saw in the last sample. The ngClass directive animation sample The ngClass directive allows us to dynamically set CSS classes. So, we can programmatically add and remove CSS from DOM elements. Classes are already used to change element styles, so it's very good to see how useful animating the ngClass directive is. Let's see a sample of ngClass so that it's easier to understand. We will create the HTML code with a Toggle ngClassbutton that will add and remove the animationClass class from the element with the initialClass class through the ngClass directive: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngClass sample</title> </head> <body> <link href="ngClassSample.css" rel="stylesheet" /> <div> <h1>ngClass Animation</h1> <div> <button ng-click="toggleNgClass = !toggleNgClass">Toggle ngClass</button> <div class="initialClass" ng-class=" {'animationClass' : toggleNgClass}"> This element has class 'initialClass' and the ngClass directive is declared as ng-class="{'animationClass' : toggleNgClass}" </div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); </script> </body> </html> For this sample, we will use two basic classes: an initial class and the class that the ngClass directive will add to and remove from the element: /* ngclass animation */ /*This is the initialClass, that keeps in the element*/ .initialClass { background-color: white; color: black; border: 1px solid black; } /* This is the animationClass, that is added or removed by the ngClass expression*/ .animationClass { background-color: black; color: white; border: 1px solid white; } To create the animation, we will define a CSS animation using keyframes; so, we only will need to use the animationClass-add and animationClass-remove classes to add animations: @-webkit-keyframes ng-class-animation { from { background-color: white; color:black; border: 1px solid black; } to { background-color: black; color: white; border: 1px solid white; } } @keyframes ng-class-animation { from { background-color: white; color:black; border: 1px solid black; } to { background-color: black; color: white; border: 1px solid white; } } The initial state is shown as follows: So, we want to display an animation when animationClass is added to the element with the initialClass class by the ngClass directive. This way, our animation selector will be: .initialClass.animationClass-add{ -webkit-animation: 1s ng-class-animation; animation: 1s ng-class-animation; } After 500 ms, the result should be a complete gray div tag because the text, border, and background colors are halfway through the transition between black and white, as we can see in this screenshot: After a second of animation, this is the result: The remove animation, which occurs when animationClass is removed, is similar to the enter animation. However, this animation should be the reverse of the enter animation, and so, the CSS selector of the animation will be: initialClass.animationClass-remove { -webkit-animation: 1s ng-class-animation reverse; animation: 1s ng-class-animation reverse; } The animation result will be the same as we saw in previous screenshots, but in the reverse order. The ngHide and ngShow animation sample Let's see one sample of the ngHide animation, which is the directive that shows and hides the given HTML code based on an expression, such as the ngShow directive. We will use this directive to create a success notification message that fades in and out. To have a lean CSS file in this sample, we will use the Bootstrap CSS library, which is a great library to use with AngularJS. There is an AngularJS version of this library created by the Angular UI team, available at http://angular-ui.github.io/bootstrap/. The Twitter Bootstrap library is available at http://getbootstrap.com/. For this sample, we will use the Microsoft CDN; you can check out the Microsoft CDN libraries at http://www.asp.net/ajax/cdn. Consider the following HTML: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngHide sample</title> </head> <body> <link href="http://ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/css/ bootstrap.css" rel="stylesheet" /> <style> /* ngHide animation */ .ngHideSample { padding: 10px; } .ngHideSample.ng-hide-add { -webkit-transition: all linear 0.3s; -moz-transition: all linear 0.3s; -ms-transition: all linear 0.3s; -o-transition: all linear 0.3s; opacity: 1; } .ngHideSample.ng-hide-add-active { opacity: 0; } .ngHideSample.ng-hide-remove { -webkit-transition: all linear 0.3s; -moz-transition: all linear 0.3s; -ms-transition: all linear 0.3s; -o-transition: all linear 0.3s; opacity: 0; } .ngHideSample.ng-hide-remove-active { opacity: 1; } </style> <div> <h1>ngHide animation</h1> <div> <button ng-click="disabled = !disabled">Toggle ngHide animation</button> <div ng-hide="disabled" class="ngHideSample bg-success"> This element has the ng-hide directive. </div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); </script> </body> </html> In this sample, we created an animation in which when the element is going to hide, its opacity is transitioned until it's set to 0. Also, when the element appears again, its opacity transitions back to 1 as we can see in the sequence of the following sequence of screenshots. In the initial state, the output is as follows: After we click on the button, the notification message starts to fade: After the add (ng-hide-add) animation has completed, the output is as follows: Then, if we toggle again, we will see the success message fading in: After the animation has completed, it returns to the initial state: The ngShow directive uses the same convention; the only difference is that each directive has the opposite behavior for the model value. When the model is true, ngShow removes the ng-hide class and ngHide adds the ng-hide class, as we saw in the first sample of this article. The ngModel directive and form animations We can easily animate form controls such as input, select, and textarea on ngModel changes. Form controls already work with validation CSS classes such as ng-valid, ng-invalid, ng-dirty, and ng-pristine. These classes are appended to form controls by AngularJS, based on validations and the current form control status. We are able to animate on the add and remove features of those classes. So, let's see an example of how to change the input color to red when a field becomes invalid. This helps users to check for errors while filling in the form before it is submitted. The animation eases the validation error experience. For this sample, a valid input will contain only digits and will become invalid once a character is entered. Consider the following HTML: <h1>ngModel and form animation</h1> <div> <form> <input ng-model="ngModelSample" ng-pattern="/^d+$/" class="inputSample" /> </form> </div> This ng-pattern directive validates using the regular expression if the model ngModelSample is a number. So, if we want to warn the user when the input is invalid, we will set the input text color to red using a CSS transition. Consider the following CSS: /* ngModel animation */ .inputSample.ng-invalid-add { -webkit-transition: 1s linear all; transition: 1s linear all; color: black; } .inputSample.ng-invalid { color: red; } .inputSample.ng-invalid-add-active { color: red; } We followed the same pattern as ngClass. So, when the ng-invalid class is added, it will append the ng-invalid-add class and the transition will change the text color to red in a second; it will then continue to be red, as we have defined the ng-invalid color as red too. The test is easy; we just need to type in one non-numeric character on the input and it will display the animation. The ngMessage and ngMessages directive animations Both the ngMessage and ngMessages directives are complimentary, but you can choose which one you want to animate, or even animate both of them. They became separated from the core module, so we have to add the ngMessages module as a dependency of our AngularJS application. These directives were added to AngularJS in Version 1.3, and they are useful to display messages based on the state of the model of a form control. So, we can easily display a custom message if an input has a specific validation error, for example, when the input is required but is not filled in yet. Without these directives, we would rely on JavaScript code and/or complex ngIf statements to accomplish the same result. For this sample, we will create three different error messages for three different validations of a password field, as described in the following HTML: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>ngMessages animation</title> </head> <body> <link href="ngMessageAnimation.css" rel="stylesheet" /> <h1>ngMessage and ngMessages animation</h1> <div> <form name="messageAnimationForm"> <label for="modelSample">Password validation input</label> <div> <input ng-model="ngModelSample" id="modelSample" name="modelSample" type="password" ng-pattern= "/^d+$/" ng-minlength="5" ng-maxlength="10" required class="ngMessageSample" /> <div ng-messages="messageAnimationForm. modelSample.$error" class="ngMessagesClass" ng-messages-multiple> <div ng-message="pattern" class="ngMessageClass">* This field is invalid, only numbers are allowed</div> <div ng-message="minlength" class="ngMessageClass">* It's mandatory at least 5 characters</div> <div ng-message="maxlength" class="ngMessageClass">* It's mandatory at most 10 characters</div> </div> </div> </form> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-messages.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate', 'ngMessages']); </script> </body> </html> We included the ngMessage file too, as it's required for this sample. For the ngMessages directive, that is, the container of the ngMessage directives, we included an animation on ng-active-addthat changes the container background color from white to red and ng-inactive-add that does the opposite, changing the background color from red to white. This works because the ngMessages directive appends the ng-active class when there is any message to be displayed. When there is no message, it appends the ng-inactive class to the element. Let's see the ngMessages animation's declaration: .ngMessagesClass { height: 50px; width: 350px; } .ngMessagesClass.ng-active-add { transition: 0.3s linear all; background-color: red; } .ngMessagesClass.ng-active { background-color: red; } .ngMessagesClass.ng-inactive-add { transition: 0.3s linear all; background-color: white; } .ngMessagesClass.ng-inactive { background-color: white; } For the ngMessage directive, which contains a message, we created an animation that changes the color of the error message from transparent to white when the message enters the DOM, and changes the color from white to transparent when the message leaves DOM, shown as follows: .ngMessageClass { color: white; } .ngMessageClass.ng-enter { transition: 0.3s linear all; color: transparent; } .ngMessageClass.ng-enter-active { color: white; } .ngMessageClass.ng-leave { transition: 0.3s linear all; color: white; } .ngMessageClass.ng-leave-active { color: transparent; } This sample illustrates two animations for two directives that are related to each other. The initial result, before we add a password, is as follows: We can see both animations being triggered when we type in the a character, for example, in the password input. Between 0 and 300 ms of the animation, we will see both the background and text appearing for two validation messages: After 300 ms, the animation has completed, and the output is as follows: The ngView directive animation The ngView directive is used to add a template to the main layout. It has support for animation, for both enter and leave events. It's nice to have an animation for ngView, so the user has a better notion that we are switching views. For this directive sample, we need to add the ngRoute JavaScript file to the HTML and the ngRoute module as a dependency of our app. We will create a sample that slides the content of the current view to the left, and the new view appears sliding from the right to the left too so that we can see the current view leaving and the next view appearing. Consider the following HTML: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngView sample</title> </head> <body> <style> .ngViewRelative { position: relative; height: 300px; } .ngViewContainer { position: absolute; width: 500px; display: block; } .ngViewContainer.ng-enter, .ngViewContainer.ng-leave { -webkit-transition: 600ms linear all; transition: 600ms linear all; } .ngViewContainer.ng-enter { transform: translateX(500px); } .ngViewContainer.ng-enter-active { transform: translateX(0px); } .ngViewContainer.ng-leave { transform: translateX(0px); } .ngViewContainer.ng-leave-active { transform: translateX(-1000px); } </style> <h1>ngView sample</h1> <div class="ngViewRelative"> <a href="#/First">First page</a> <a href="#/Second">Second page</a> <div ng-view class="ngViewContainer"> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-route.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate', 'ngRoute']); app.config(['$routeProvider', function ($routeProvider) { $routeProvider .when('/First', { templateUrl: 'first.html' }) .when('/Second', { templateUrl: 'second.html' }) .otherwise({ redirectTo: '/First' }); }]); </script> </body> </html> We need to configure the routes on config, as the JavaScript shows us. We then create the two HTML templates on the same directory. The content of the templates are just plain lorem ipsum. The first.html file content is shown as follows: <div> <h2>First page</h2> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras consectetur dui nunc, vel feugiat lectus imperdiet et. In hac habitasse platea dictumst. In rutrum malesuada justo, sed porttitor dolor rutrum eu. Sed condimentum tempus est at euismod. Donec in faucibus urna. Fusce fermentum in mauris at pretium. Aenean ut orci nunc. Nulla id velit interdum nibh feugiat ultricies eu fermentum dolor. Pellentesque lobortis rhoncus nisi, imperdiet viverra leo ullamcorper sed. Donec condimentum tincidunt mollis. Curabitur lorem nibh, mattis non euismod quis, pharetra eu nibh. </p> </div> The second.html file content is shown as follows: <div> <h2>Second page</h2> <p> Ut eu metus vel ipsum tristique fringilla. Proin hendrerit augue quis nisl pellentesque posuere. Aliquam sollicitudin ligula elit, sit amet placerat augue pulvinar eget. Aliquam bibendum pulvinar nisi, quis commodo lorem volutpat in. Donec et felis sit amet mauris venenatis feugiat non id metus. Fusce leo elit, egestas non turpis sed, tincidunt consequat tellus. Fusce quis auctor neque, a ultricies urna. Cras varius purus id sagittis luctus. Sed id lectus tristique, euismod ipsum ut, congue augue. </p> </div> Great, we now have our app set up to enable ngView and routes. The animation was defined by adding animation to the enter and leave events, using translateX(). This animation is defined to the new view coming from 500 px from the right and animating until the position on the x-axis is 0, leaving the view in the left corner. The leaving view goes from the initial position until it is at -1000 px on the x-axis. Then, it leaves the DOM. This animation creates a sliding effect; the leaving view leaves faster as it has to move the double of the distance of the entering view in the same animation duration. We can change the translation using the y-axis to change the animation direction, creating the same sliding effect but with different aesthetics. The ngSwitch directive animation The ngSwitch directive is a directive that is used to conditionally swap the DOM structure based on an expression. It supports animation on the enter and leave events, for example, the ngView directive animation events. For this sample, we will create the same sliding effect of the ngView sample, but in this case, we will create a sliding effect from top to bottom instead of right to left. This animation helps the user to understand that one item is being replaced by the other. The ngSwitch sample HTML is shown as follows: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngSwitch sample</title> </head> <body> <div ng-controller="animationsCtrl"> <h1>ngSwitch sample</h1> <p>Choose an item:</p> <select ng-model="ngSwitchSelected" ng-options="item for item in ngSwitchItems"></select> <p>Selected item:</p> <div class="switchItemRelative" ng-switch on="ngSwitchSelected"> <div class="switchItem" ng-switch-when="item1">Item 1</div> <div class="switchItem" ng-switch-when="item2">Item 2</div> <div class="switchItem" ng-switch-when="item3">Item 3</div> <div class="switchItem" ng-switch-default>Default Item</div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); app.controller('animationsCtrl', function ($scope) { $scope.ngSwitchItems = ['item1', 'item2', 'item3']; }); </script> </body> </html> In the JavaScript controller, we added the ngSwitchItems array to the scope, and the animation CSS is defined as follows: /* ngSwitch animation */ .switchItemRelative { position: relative; height: 25px; overflow: hidden; } .switchItem { position: absolute; width: 500px; display: block; } /*The transition is added when the switch item is about to enter or about to leave DOM*/ .switchItem.ng-enter, .switchItem.ng-leave { -webkit-transition: 300ms linear all; -moz-transition: 300ms linear all; -ms-transition: 300ms linear all; -o-transition: 300ms linear all; transition: 300ms linear all; } /* When the element is about to enter DOM*/ .switchItem.ng-enter { bottom: 100%; } /* When the element completes the enter transition */ .switchItem.ng-enter-active { bottom: 0; } /* When the element is about to leave DOM*/ .switchItem.ng-leave { bottom: 0; } /*When the element end the leave transition*/ .switchItem.ng-leave-active { bottom: -100%; } This is almost the same CSS as the ngView sample; we just used the bottom property, added a different height to the switchItemRelative class, and included overflow:hidden. The ngInclude directive sample The ngInclude directive is used to fetch, compile, and include an HTML fragment; it supports animations for the enter and leave events, such as the ngView and ngSwitch directives. For this sample, we will use both templates created in the last ngView sample, first.html and second.html. The ngInclude animation sample HTML with JavaScript and CSS included is shown as follows: <!DOCTYPE html> <html ng-app="myApp"> <head> <title>AngularJS ngInclude sample</title> </head> <body> <style> .ngIncludeRelative { position: relative; height: 500px; overflow: hidden; } .ngIncludeItem { position: absolute; width: 500px; display: block; } .ngIncludeItem.ng-enter, .ngIncludeItem.ng-leave { -webkit-transition: 300ms linear all; transition: 300ms linear all; } .ngIncludeItem.ng-enter { top: 100%; } .ngIncludeItem.ng-enter-active { top: 0; } .ngIncludeItem.ng-leave { top: 0; } .ngIncludeItem.ng-leave-active { top: -100%; } </style> <div ng-controller="animationsCtrl"> <h1>ngInclude sample</h1> <p>Choose one template</p> <select ng-model="ngIncludeSelected" ng-options="item.name for item in ngIncludeTemplates"></select> <p>ngInclude:</p> <div class="ngIncludeRelative"> <div class="ngIncludeItem" nginclude=" ngIncludeSelected.url"></div> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/angularjs /1.3.0/angular-animate.min.js"></script> <script> var app = angular.module('myApp', ['ngAnimate']); app.controller('animationsCtrl', function ($scope) { $scope.ngIncludeTemplates = [{ name: 'first', url: 'first.html' }, { name: 'second', url: 'second.html' }]; }) </script> </body> </html> In the JavaScript controller, we included the templates array. Finally, we can animate ngInclude using CSS. In this sample, we will animate by sliding the templates using the top property, using the enter and leave events animation. To test this sample, just change the template value selected. Do it yourself exercises The following are some exercises that you can refer to as an exercise that will help you understand the concepts of this article better: Create a spinning loading animation, using the ngShow or ngHide directives that appears when the scope controller variable, $scope.isLoading, is equal to true. Using exercise 1, create a gray background layer with opacity 0.5 that smoothly fills the entire page behind the loading spin, and after page content is loaded, covers all the content until isProcessing becomes false. The effect should be that of a drop of ink that is dropped on a piece of paper and spreads until it's completely stained. Create a success notification animation, similar to the ngShow example, but instead of using the fade animation, use a slide-down animation. So, the success message starts with height:0px. Check http://api.jquery.com/slidedown/ for the expected animation effect. Copy any animation from the http://capptivate.co/ website, using AngularJS and CSS animations. Summary In this article, we learned how to animate AngularJS native directives using the CSS transitions and CSS keyframe concepts. This article taught you how to create animations on AngularJS web apps. Resources for Article: Further resources on this subject: Important Aspect of AngularJS UI Development [article] Setting Up The Rig [article] AngularJS Project [article]
Read more
  • 0
  • 0
  • 3109
article-image-using-indexes-manipulate-pandas-objects
Packt
05 Sep 2013
4 min read
Save for later

Using indexes to manipulate pandas objects

Packt
05 Sep 2013
4 min read
(For more resources related to this topic, see here.) Getting ready A good understanding of indexes in pandas is crucial to quickly move the data around. From a business intelligence perspective, they create a distinction similar to that of metrics and dimensions in an OLAP cube. To illustrate this point, this recipe walks through getting stock data out of pandas, combining it, then reindexing it for easy chomping. How to do it... Use the DataReader object to transfer stock price information into a DataFrame and to explore the basic axis of Panel. > from pandas.i git push -u origin master o.data import DataReader > tickers = ['gs', 'ibm', 'f', 'ba', 'axp'] > dfs = {} > for ticker in tickers: dfs[ticker] = DataReader(ticker, "yahoo", '2006-01-01') # a yet undiscussed data structure, in the same way the a # DataFrame is a collection of Series, a Panel is a collection of # DataFrames > pan = pd.Panel(dfs) > pan <class 'pandas.core.panel.Panel'> Dimensions: 5 (items) x 1764 (major_axis) x 6 (minor_axis)Items axis: axp to ibm Major_axis axis: 2006-01-03 00:00:00 to 2013-01-04 00:00:00 Minor_axis axis: Open to Adj Close > pan.items Index([axp, ba, f, gs, ibm], dtype=object) > pan.minor_axis Index([Open, High, Low, Close, Volume, Adj Close], dtype=object) > pan.major_axis <class 'pandas.tseries.index.DatetimeIndex'>[2006-01-03 00:00:00, ..., 2013-01-04 00:00:00] Length: 1764, Freq: None, Timezone: None Use the axis selectors to easily compute different sets of summary statistics. > pan.minor_xs('Open').mean() axp 46.227466 ba 70.746451 f 9.135794 gs 151.655091 ibm 129.570969 # major axis is sliceable as well > day_slice = pan.major_axis[1] > pan.major_xs(day_slice)[['gs', 'ba']] ba gs Open 70.08 127.35 High 71.27 128.91 Low 69.86 126.38 Close 71.17 127.09 Volume 3165000.00 4861600.00 Adj Close 60.43 118.12 Convert the Panel to a DataFrame. > dfs = [] > for df in pan: idx = pan.major_axis idx = pd.MultiIndex.from_tuples(zip([df]*len(idx), idx)) idx.names = ['ticker', 'timestamp'] dfs.append(pd.DataFrame(pan[df].values, index=idx, columns=pan.minor_axis)) > df = pd.concat(dfs) > df Data columns: Open 8820 non-null values High 8820 non-null values Low 8820 non-null values Close 8820 non-null values Volume 8820 non-null values Adj Close 8820 non-null values dtypes: float64(6) Perform the analogous operations as in the preceding examples on the newly created DataFrame. # selecting from a MultiIndex isn't much different than the Panel # (output muted) > df.ix['gs':'ibm'] > df['Open'] How it works... The previous example was certainly contrived, but when indexing and statistical techniques are incorporated, the power of pandas begins to come through. Statistics will be covered in an upcoming recipe. pandas' indexes by themselves can be thought of as descriptors of a certain point in the DataFrame. When ticker and timestamp are the only indexes in a DataFrame, then the point is individualized by the ticker, timestamp, and column name. After the point is individualized, it's more convenient for aggregation and analysis. There's more... Indexes show up all over the place in pandas so it's worthwhile to see some other use cases as well. Advanced header indexes Hierarchical indexing isn't limited to rows. Headers can also be represented by MultiIndex, as shown in the following command line: > header_top = ['Price', 'Price', 'Price', 'Price', 'Volume', 'Price'] > df.columns = pd.MultiIndex.from_tuples(zip(header_top, df.columns) Performing aggregate operations with indexes As a prelude to the following sections, we'll do a single groupby function here since they work with indexes so well. > df.groupby(level=['tickers', 'day'])['Volume'].mean() This answers the question for each ticker and for each day (not date), that is, what was the mean volume over the life of the data. Summary This article talks about the use and importance of indexes in pandas. It also talks about different operations that can be done with indexes. Resources for Article : Further resources on this subject: Installing Panda3D [Article] Setting Up Panda3D and Configuring Development Tools [Article] Collision Detection and Physics in Panda3D Game Development [Article]
Read more
  • 0
  • 0
  • 3109

Packt
24 Sep 2015
8 min read
Save for later

Snap – The Code Snippet Sharing Application

Packt
24 Sep 2015
8 min read
In this article by Joel Perras, author of the book Flask Blueprints, we will build our first fully functional, database-backed application. This application with the codename, Snap, will allow users to create an account with a username and password. In this account, users will be allowed to add, update, and delete the so-called semiprivate snaps of text (with a focus on lines of code) that can be shared with others. For this you should be familiar with at least one of the following relational database systems: PostgreSQL, MySQL, or SQLite. Additionally, some knowledge of the SQLAlchemy Python library, which acts as an abstraction layer and object-relational mapper for these (and several other) databases, will be an asset. If you are not well versed in the usage of SQLAlchemy, fear not. We will have a gentle introduction to the library that will bring the new developers up to speed and serve as a refresher for the more experienced folks. The SQLite database will be our relational database of choice due to its very simple installation and operation. The other database systems that we listed are all client/server-based with a multitude of configuration options that may need adjustment depending on the system they are installed in, while SQLite's default mode of operation is self-contained, serverless, and zero-configuration. Any major relational database supported by SQLAlchemy as a first-class citizen will do. (For more resources related to this topic, see here.) Diving In To make sure things start correctly, let's create a folder where this project will exist and a virtual environment to encapsulate any dependencies that we will require: $ mkdir -p ~/src/snap && cd ~/src/snap $ mkvirtualenv snap -i flask This will create a folder called snap at the given path and take us to this newly created folder. It will then create the snap virtual environment and install Flask in this environment. Remember that the mkvirtualenv tool will create the virtual environment, which will be the default set of locations to install the packages from pip, but the mkvirtualenv command does not create the project folder for you. This is why we will run a command to create the project folder first and then create the virtual environment. Virtual environments, by virtue of the $PATH manipulation performed once they are activated, are completely independent of where in your file system your project files exist. We will then create our basic blueprint-based project layout with an empty users blueprint: application ├── __init__.py ├── run.py └── users ├── __init__.py ├── models.py └── views.py Flask-SQLAlchemy Once this has been established, we need to install the next important set of dependencies: SQLAlchemy, and the Flask extension that makes interacting with this library a bit more Flask-like, Flask-SQLAlchemy: $ pip install flask-sqlalchemy This will install the Flask extension to SQLAlchemy along with the base distribution of the latter and several other necessary dependencies in case they are not already present. Now, if we were using a relational database system other than SQLite, this is the point where we would create the database entity in, say, PostgreSQL along with the proper users and permissions so that our application can create tables and modify the contents of these tables. SQLite, however, does not require any of that. Instead, it assumes that any user that has access to the filesystem location that the database is stored in should also have permission to modify the contents of this database. For the sake of completeness, however, here is how one would create an empty database in the current folder of your filesystem: $ sqlite3 snap.db # hit control-D to escape out of the interactive SQL console if necessary.   As mentioned previously, we will be using SQLite as the database for our example applications and the directions given will assume that SQLite is being used; the exact name of the binary may differ on your system. You can substitute the equivalent commands to create and administer the database of your choice if anything other than SQLite is being used. Now, we can begin the basic configuration of the Flask-SQLAlchemy extension. Configuring Flask-SQLAlchemy First, we must register the Flask-SQLAlchemy extension with the application object in the application/__init__.py: from flask import Flask fromflask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../snap.db' db = SQLAlchemy(app) The value of app.config['SQLALCHEMY_DATABASE_URI'] is the escaped relative path to the snap.db SQLite database that we created previously. Once this simple configuration is in place, we will be able to create the SQLite database automatically via the db.create_all() method, which can be invoked in an interactive Python shell: $ python >>>from application import db >>>db.create_all() This should be an idempotent operation, which means that nothing would change even if the database already exists. If the local database file did not exist, however, it would be created. This also applies to adding new data models: running db.create_all() will add their definitions to the database, ensuring that the relevant tables have been created and are accessible. It does not, however, take into account the modification of an existing model/table definition that already exists in the database. For this, you will need to use the relevant tools (for example, the sqlite CLI) to modify the corresponding table definitions to match those that have been updated in your models or use a more general schema tracking and updating tool such as Alembic to do the majority of the heavy lifting for you. SQLAlchemy basics SQLAlchemy is, first and foremost, a toolkit to interact with the relational databases in Python. While it provides an incredible number of features—including the SQL connection handling and pooling for various database engines, ability to handle custom datatypes, and a comprehensive SQL expression API—the one feature that most developers are familiar with is the Object Relational Mapper. This mapper allows a developer to connect a Python object definition to a SQL table in the database of their choice, thus allowing them the flexibility to control the domain models in their own application and requiring only minimal coupling to the database product and the engine-specific SQLisms that each of them exposes. While debating the usefulness (or the lack thereof) of an object relational mapper is outside the scope of for those who are unfamiliar with SQLAlchemy we will provide a list of benefits that using this tool brings to the table, as follows: Your domain models are written to interface with one of the most well-respected, tested, and deployed Python packages ever created—SQLAlchemy. Onboarding new developers to a project becomes an order of magnitude easier due to the extensive documentation, tutorials, books, and articles that have been written about using SQLAlchemy. Import-time validation of queries written using the SQLAlchemy expression language; instead of having to execute each query string against the database to determine if there is a syntax error present. The expression language is in Python and can thus be validated with your usual set of tools and IDE. Thanks to the implementation of design patterns such as the Unit of Work, the Identity Map, and various lazy loading features, the developer can often be saved from performing more database/network roundtrips than necessary. Considering that the majority of a request/response cycle in a typical web application can easily be attributed to network latency of one form or another, minimizing the number of database queries in a typical response is a net performance win on many fronts. While many successful, performant applications can be built entirely on the ORM, SQLAlchemy does not force it upon you. If, for some reason, it is preferable to write raw SQL query strings or to use the SQLAlchemy expression language directly, then you can do that and still benefit from the connection pooling and the Python DBAPI abstraction functionality that is the core of SQLAlchemy itself. Now that we've given you several reasons why you should be using this database query and domain data abstraction layer, let's look at how we would go about defining a basic data model. Summary After having gone through this article we have seen several facets of how Flask may be augmented with the use of extensions. While Flask itself is relatively spartan, the ecology of extensions that are available make it such that building a fully fledged user-authenticated application may be done quickly and relatively painlessly. Resources for Article: Further resources on this subject: Creating Controllers with Blueprints[article] Deployment and Post Deployment [article] Man, Do I Like Templates! [article]
Read more
  • 0
  • 0
  • 3109
Modal Close icon
Modal Close icon