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-report-components-nav-2009-part-1
Packt
30 Nov 2009
13 min read
Save for later

Report components in NAV 2009: Part 1

Packt
30 Nov 2009
13 min read
Report components overview What we generally refer to as the report or report object is technically referred to as a Report Description. The Report Description is the information describing the layout for the planned output and processing logic to be followed when processing the data. Report Descriptions are stored in the database in the same way as other table or form/page descriptions. As with pages, we will use the term "report" whether we mean the output, the description, or the object. Reports share some attributes with pages including aspects of the designer, features of various controls, some triggers, and even some of the properties. Where those parallels exist, we should take notice of them. The consistency of any toolset, including NAV, makes it easier to learn and to use. This applies to developers as well as to the users. The overall structure of an NAV RTC Report consists of the following elements. Any particular report may utilize only a small number of the possible elements (for example, Section Triggers are not used by the RTC), but many different combinations are feasible and logical. Report Properties Report Triggers Data Items Data Item Properties Data Item Triggers Data Item Sections Section Triggers Data Field Controls Visual Studio Layout VS Controls VS Control Properties Request Page Request Page Properties Request Page Triggers Request Page Controls Request Page Control Properties Request Page Control Triggers The components of a report description A report description consists of a number of primary components, each of which in turn is made up of secondary components. The primary components Report Properties and Triggers and Data Item Properties and Triggers define the data flow and overall logic for processing the data. These are all designed in the C/SIDE Report Designer. A subordinate set of primary components, Data Field Controls and Working Storage, are defined within the DataItem Sections, which are also designed in the C/SIDE Report Designer. Data Fields are defined in this article as the fields contained in the DataItems (that is application tables). Working Storage (also referred to as Working Data) fields are defined in this article as the data elements that are created within a report (or other object) for use in that object. Working Storage data elements are not permanently stored in the database. These components constitute the data elements that will be made available to the Visual Studio Report Designer (VS RD). The VS RD cannot access any data elements that have not been defined within the Report Sections (each of which must be associated with a DataItem). The Report Layout  is designed in the VS RD using the data elements made available to the VS RD by the C/SIDE RD, defined in the DataItem Sections. The Report Layout includes the Page Header, Body, and Page Footer. In most cases, the Body of the report is based on a layout table. Note that the VS RD layout table is a data grid used for layout purposes and is not the same as a table of data stored in the NAV database. This terminology is confusing. When the NAV Help files regarding reports refer to a table, you will have to read very carefully to determine which meaning for "table" is intended. Within the Report Body, there can be none, one, or more Detail rows. There can also be Header and Footer rows. The Detail rows are the definition of the primary, repeating data display. A report layout may also include one or more Group rows, used to group and total data that is displayed in the Detail row(s). All of the report formatting is controlled in the Report Layout. The Font, field positioning, visibility options (including expand/collapse sections), dynamic sorting, and graphics are all defined as part of the Report Layout. The same is true for pagination control, headings and footers, some totaling, column-width control, and a number of other display details. Of course, if the display target changes dramatically in the future versions of NAV, for example, from a desktop workstation display to a browser supporting cellular phone, then the appearance of the Report Layout will change dramatically as well. One of the advantages of SSRS is to support such a level of flexibility. But, if you expect that degree of variability in output devices, you will have design accordingly. There is another primary functional component of a report description, the Request Page. It displays as a page when a report is invoked. The purpose of the Report Request Page is to allow users to enter information to control the report. Control information entered through a Request Page may include filters, control dates, other control parameters, and specifi cations as well as defining which available formatting or processing options to use for this instance of the report (that is for this run). The Request Page appears once at the beginning of a report at run time. Report Data Flow One of the principal advantages of the NAV report is its built-in data flow structure. At the beginning of any report, you must define the data item(s), the tables that the report will process. It is possible to create a working report that has no data items, but that situation normally calls for a codeunit to be used. There are rare exceptions to this, such as a report created for the purposes of processing only, perhaps to control branching or choice of objects to be run subsequently. In that case, you might have no data item, just a set of logic whose data flow is totally self-controlled. Normally in a report, NAV automatically creates a data flow process for each data item. This automatically created data flow provides specific triggers and processing events: Preceding the data For each record of the data Following the end of the data The underlying "black-box" report logic (the part we can't see or affect) loops through the named tables, reading and processing one record at a time. That flow is automatic, that is we don't have to program it. Therefore, any time we need a process that steps through a set of data one record at a time, it is quite likely we will use a report object. If you've ever worked with some of the legacy report writers or the RPG programming language, it is likely that you will recognize this looping behavior. That recognition may allow you to understand how to take advantage of NAV reports more quickly. The reference to a database table in a report is referred to as a Data Item. One of the capabilities of the report data flow structure is the ability to nest data items. If Data Item 2 is nested within Data Item 1 and related to Data Item 1, then for each record in Data Item 1, all of the related records in Data Item 2 will be processed. The next screenshot shows the data item definition screen. This example uses tables from our ICAN system. The design is for a report to list all the Gifts by Donor for each Donor Type. Thus Donor Type is the primary table (DataItem1). For each Donor Type, we want to list all the Donors that have given Gifts to ICAN (DataItem2). And for each Donor of each Donor Type, we want to list their Gifts which are recorded in the Gift Ledger (DataItem3). On the Data Item screen, we initially enter the table name Donor, as you see in the following screenshot. The Data Item Name, to which the C/AL code will refer, is DataItem1 in our example here. When we enter the second table, Donor, then we click on the right arrow at the bottom of the screen. That will cause the selected data item to be indented relative to the data item above (the "superior" data item). That causes the nesting of the processing of the indented data item within the processing of the superior data item. In this instance, we have renamed the Data Items just for the purpose of our example, in order to illustrate data flow within a report. The normal default behavior would be for the Name in the right column to default to the table name shown in the left column (for example, the Name for Donor would be displayed as < Donor > by default). This default Data Item Name would only need to be changed if the same table appeared twice within the Data Item list. For the second instance of Donor, for example, you could simply give it the Name Donor2. For each record in the superior data item, the indented data item will be fully processed. Which records are actually processed in the indented table will depend on the filters, and the defined relationships between the superior and indented tables. In other words, the visible indentation is only part of the necessary definition. We'll review the rest of it shortly. For our example, we enter a third table, Gift Ledger, and enter our example name of DataItem3. The following chart shows the data flow for this Data Item structure. The chart boxes are intended to show the nesting that results from the indenting of the Data Items in the preceding screenshot. The Donor Data Item is indented under the Donor Type Data Item. That means for every processed Donor Type record, all of the selected Donor records will be processed. That same logic applies to the Donor records and Gift Ledger records (that is, for each Donor record processed, all selected Gift records are processed). The blocks visually illustrate how the data item nesting controls the data flow. As you can see, the full range of processing for DataItem2 occurs for each DataItem1 record. In turn, the full range of processing for DataItem3 occurs for each DataItem2 record. In Classic Client reporting, the formatting and output for each record processed happened in sequence as the last step in processing that record. In other words, once a record was read and processed, it was rendered for output presentation before the next record was read. In the NAV 2009 Role Tailored Client, report processing occurs in two separate steps, the first tied primarily to what has been designed in the Classic RD, the second tied to what has been designed in the VS RD. The processing of data represented in the preceding image occurs in the first step, yielding a complete dataset containing all the data that is to be rendered for output. This intermediate dataset is a flattened version of the hierarchically structured dataset represented in the Classic RD. Each record in the new dataset contains all the fields from the sections (parent, child, grandchild, and so on) "de-normalized" into a completely flat data structure. This structure also includes Grouping, Filtering, Formatting, MultiLanguage, and other control information required to allow the Visual Studio Report Viewer to properly render the defined report. That flattened dataset is then handed off to the Visual Studio Microsoft Report Viewer. The Microsoft Report Viewer provides the new NAV 2009 reporting capabilities such as various types of graphics, interactive sorting and expand/collapse sections, output to PDF and Excel, and other advanced reporting features based on RDLC created by the VS RD design work. The elements of a report Earlier we reviewed a list of the elements of a Report object. Now we're going to learn about each of those elements. Our goal here is to understand how the pieces of the report puzzle fit together to form a useful, coherent whole. Following that, we will do some development work for our ICAN system to apply some of what we've reviewed. Report properties The Classic RD Report Properties are shown in the following screenshot. Some of these properties have essentially the same purpose as those in pages and other objects. Many of these Report Property settings only apply to Classic reports and are replaced by equivalent Report Properties in the Visual Studio RD. ID: The unique report object number. Name: The name by which this report is referred to within C/AL code. Caption: The name that is displayed for this report; Caption defaults to Name. CaptionML: The Caption translation for a defined alternative language. ShowPrintStatus: If this property is set to Yes and the ProcessingOnly property is set to No, then a Report Progress window, including a Cancel button, is displayed. When ProcessingOnly is set to Yes, if you want a Report Progress Window, you must create your own dialog box. UseReqForm: Determines if a Request Page should be displayed to allow the user the choice of Sort Sequence and entry of filters and other requested control information. UseSystemPrinter: Determines if the default printer for the report should be the defined system printer, or if NAV should check for a setup-defined User/Report printer definition. ProcessingOnly: This should be set to Yes when the report object is being used only to process data and no report output is to be generated. If this property is set to Yes, then that overrides any other property selections that would apply in a report-generating situation. TransactionType: This can be in one of four basic options: Browse, Snapshot, UpdateNoLocks, and Update. These control the record locking behavior to be applied in this report. The default is UpdateNoLocks. This property is generally only used by advanced developers. Description: This is for internal documentation; it is not used often. TopMargin, BottomMargin, LeftMargin, RightMargin: Does not apply to an RTC report. There are applicable VS RD properties. HorzGrid, VertGrid: Does not apply to an RTC report. VS RD layout has its own grid for control positioning. Permissions: This provides report-specific setting of permissions, which are the rights to access data, subdivided into Read, Insert, Modify, and Delete. This allows the developer to define report and processing permissions that override the user-by-user permissions security setup. The following printer-specific properties do not apply to an RTC report. Several can be overridden by user selections made at run time. Orientation: There is an applicable VS RD property PaperSize: There is an applicable VS RD property PaperSourceFirstPage, PaperSourceOtherPages: This is controlled in Page Setup for RTC reports DeviceFontName: This is controlled by the Report Viewer The Visual Studio RD Report Properties are shown in the following screenshot: Report triggers The following screenshot shows the Report triggers available in a report: Documentation(): Documentation is technically not a trigger, but a section which serves only the purpose of containing whatever documentation you care to put there. No C/AL code is in a Documentation section. You have no format restrictions, other than common sense and your defined practices. OnInitReport(): It executes once when the report is opened. OnPreReport(): It executes once after the Request Page completes. All the Data Item processing follows this trigger. OnPostReport(): If the report is completed normally, this trigger executes once at the end of all of the other report processing. All the Data Item processing precedes this trigger. OnCreateHyperlink(): It does not apply to an RTC report. OnHyperlink(): It does not apply to an RTC report. There are general explanations of Report Triggers in the online C/SIDE Reference Guide (Help); you should also review those explanations.
Read more
  • 0
  • 0
  • 3411

article-image-drupal-6-performance-optimization-using-db-maintenance-and-boost-part-1
Packt
23 Mar 2010
8 min read
Save for later

Drupal 6 Performance Optimization Using DB Maintenance and Boost: Part 1

Packt
23 Mar 2010
8 min read
These are not required modules, but rather are recommended modules to add to your Drupal performance arsenal. The way this article will work is that we'll outline the purpose of each module, install and configure it, and then use it on a specific topic, for example, within your site. This will give you some practice using contributed Drupal modules and also a look at the variety of performance based modules that are available from the Drupal project community. Using the DB Maintenance module The DB Maintenance module can be used to optimize your MySQL database tables. Depending on the type of database you are running, the module allows you to use a function called OPTIMIZE TABLE, which troubleshoots and then optimizes various errors in your MySQL tables. For MyISAM tables, the OPTIMIZE TABLE will repair your database tables if they have deleted rows. For BDB and InnoDB types of tables the function will rebuild the entire table. You can use this module in tandem with phpMyAdmin to determine if you do or do not need to optimize your database tables. The benefit of this module is that it allows you to keep your database optimized and defragmented, similar to keeping your computer hard drive optimized and defragmented so that it runs faster, and you can do all this from the Drupal administrative interface. The project page where you can download the module is here: http://drupal.org/project/db_maintenance. Download the module tar.gz and extract it to your desktop. Then, upload the files through FTP, or upload and extract using a cPanel utility if your host provides this. The module should go in your /sites/all/modules directory. Once you upload and extract the module folder, enable the module on your modules admin page and save your configuration. We'll use the version that's recommended for Drupal 6.x, which is 6.x-1.1. You can try out the beta version, but you should not run this beta version on a production level website unless you've tested it sufficiently in a sandbox environment. Once you save your module configuration, you'll notice that the module adds a link to its settings and configuration page under your main Site configuration section. Go to Site configuration | DB maintenance to access the configuration admin screen for the module. The DB maintenance screen will contain a checkbox at the top allowing you to log OPTIMIZE queries. If you check this box, your watchdog log entries module will log all table optimization entries and give you detailed information on the tables that were optimized. At the time of writing this article, the 1.1 version of the DB Maintenance module contained bugs that caused glitches with the method of adding this module's queries to the recent log entries or prevented this entirely. You may also experience these glitches. The module's developers are aware of the issues because they have been posted to the issue queue at http://drupal.org/ on the module project page. Let's go ahead and check this box. You can then select the frequency with which you would like to run the optimization. The choices are daily, Run during every cron, Hourly, Bi-Hourly, Daily, Bi-Daily, Weekly, Bi-Weekly, Monthly, and Bi-Monthly. You can also click on the Optimize now link to force the optimization to occur immediately without scheduling in advance. We'll click on this link for the purpose of this demo, but in future you may want to schedule the optimization. We'll then run a cron job through the Status report, or a module such as Poormanscron, and the tables will be optimized. Next, you can select the tables in your Drupal database that you want to optimize. A nice feature of this module is that it allows you to multi select database tables, only select a few tables, or just one table. This gives you the same flexibility and functionality as your phpMyAdmin tool, but you can run everything from within your Drupal interface. It's like a phpMyAdmin lite version right in your Drupal site. This is a preferred option for those developers who may not have immediate access to a client's phpMyAdmin or a host's database management utility. Choose a selection of tables that you want to optimize, or select all the tables. For this demo I'm going to optimize all of my content type tables, so I'll select all of those. I'll also optimize my block tables: blocksblocks_rolescontent_type_blogcontent_type_bookcontent_type_forumcontent_type_pagecontent_type_photocontent_type_pollcontent_type_storycontent_type_webform Once you've selected the tables you want to optimize, click on the Optimize now link. As with any module or optimization enhancement that you make to your Drupal site, it is good practice to run a full backup of your MySQL database before performing any maintenance, including optimizing tables using the DB Maintenance module. This way you will have a full backup of your data if you run into any issues that the module could potentially create. It's better to play it safe and perform the backup first. Once you click on the Optimize now link, you should receive a message notifying you that the Database tables are optimized. This concludes our discussion and walkthrough of using the DB Maintenance module. Let's now turn to the Boost module and use it to speed up our site page and content loads. Using the Boost module We' re going to turn our attention to the Boost module in this section. Boost is a contributed module that allows you to run incredibly advanced static page caching on your Drupal site. This caching mechanism will help to increase performance and scalability on your site, especially if it gets heavy traffic and anonymous page visits, and it is on a shared hosting environment. This is usually the first contributed performance-based module to turn to for help when you host your Drupal site on a shared server. Developers running Drupal sites on shared servers and running sites that serve predominantly anonymous Drupal users will definitely want to try out this module. It's also a fun module to use from a technical standpoint because you can see the results immediately, as you configure it. The Drupal project page for the module is here: http://drupal.org/project/boost. There is a wealth of detailed information about the module on this project page, including announcements about upcoming conference presentations that focus on the Boost module, testimonials, install instructions, and links to documentation and associated modules that you may want to run alongside Boost. It is very popular and has quite a following in the Drupal development community. I definitely recommend reading about this module and all of its install and configuration instructions in detail before attempting to use it. The install paragraph suggests reading through the module README.txt file before running the install for details on how the module works. There are also detailed instructions and documentation on the module here: http://drupal.org/node/545664. Note that the one requirement to use this module is that your Drupal site must have clean URLs configured and enabled. It's a good idea to make sure you are running clean URLs on your site before you start installing and configuring Boost. Additionally, there are some recommended modules that the developers encourage you to install in tandem with the Boost module. We will install two of these modules: Global Redirect and Transliteration. The Global Redirect module runs a number of checks on your website including the following: Checks the current URL for a Drupal path alias and does a 301 redirect to the URL if it is not being used. Checks the current URL for a trailing / and removes the slash if it's present in Drupal URLs. Checks if the current URL is the same as the site's front page and redirects to the front page if it locates a match. Checks to see if you are using clean URLs. If you do have clean URLs enabled, this module ensures URLs are accessed using the clean URL method rather than an unclean method (for example, ?q=user). Checks access to the URL. If a user does not have permissions to view the URL, then no redirects are allowed. This helps to protect private URL aliases. Checks to ensure the alias matches the URL it is aliasing. So, if you have a URL alias such as /about and this directs to node/23, then a user on your site can access the page using either of those URLs. The Transliteration module removes white space and non-ASCII characters in your URLs. For example, it will try and add underscores to fill white space in a URL. Installing and enabling these two modules will help remove glitches and errors in your site's path structure. If you haven't already, we'll also take the time now to install the Poormanscron module and set up and configure automatic cron runs instead of having to continue running cron manually. We'll return to installing and configuring Poormanscron later in this article, but just keep it on your radar for now. Let's go ahead and install the Boost module and take a closer look at some of its features.
Read more
  • 0
  • 0
  • 3410

article-image-raspberry-pi-gaming-operating-systems
Packt
19 Feb 2015
3 min read
Save for later

Raspberry Pi Gaming Operating Systems

Packt
19 Feb 2015
3 min read
In this article by Shea Silverman, author of the book Raspberry Pi Gaming Second Edition, we will see how the Raspberry Pi, while a powerful little device, is nothing without software to run on it. Setting up emulators, games, and an operating system can be a daunting task for those who are new to using Linux. Luckily, there are distributions (operating system images) that handle all of this for us. In this article, we will demonstrate a distribution that have been specially made for gaming. (For more resources related to this topic, see here.) PiPlay PiPlay is an open source premade distribution that combines numerous emulators, games, and a custom frontend that serves as the GUI for the Raspberry Pi. Created in 2012, PiPlay started as PiMAME. Originally, PiMAME was a version of Raspbian that included the AdvanceMAME and AdvanceMENU frontend. The distribution was set to autologin and start up AdvanceMENU at boot up. This project was founded because of the numerous issues users were facing to get MAME to compile and run on their own devices. As more and more emulators were released, PiMAME began to include them in the image, and changed its name to PiPlay, as it wasn't just for arcade emulation anymore. Currently, PiPlay contains the following emulators and games: AdvanceMAME (Arcade) MAME4ALL (Arcade) Final Burn Alpha (Capcom and Neo Geo) PCSX_ReARMed (PlayStation) Dgen (Genesis) SNES9x (Super Nintendo) FCEUX (NES) Gearboy (Gameboy) GPSP (Gameboy Advance) ScummVM (point-and-click games) Stella (Atari 2600) NXEngine (Cave Story) VICE (Commodore 64) Mednafen (Game Gear, Neo Geo Pocket Color, Sega Master System, Turbo Grafx 16/PC-Engine) To download the latest version of PiPlay, go to http://piplay.org and click on the Download option. Now you need to burn the PiPlay image to your SD card. When this is completed, insert the SD card into your Raspberry Pi and turn it on. Within a few moments, you should see an image like this on your screen: Once it's finished booting, you will be presented with the PiPlay menu screen: Here, you will see all the different emulators and tools you have available. PiPlay includes an extensive controller setup tool. By pressing Tab key or button 3 on your controller, a popup window will appear. Select Controller Setup and follow the onscreen guide to properly configure your controller: At the moment, there isn't much to do because you haven't loaded any games for the emulators. The easiest way to load your game files into PiPlay is to use the web frontend. If you connect your Pi to your network, an IP address should appear at the top right of your screen. Another way to find out your IP address is by running the command ifconfig on the command line. Navigate your computer's web browser to this address, and the PiPlay frontend will appear: Here, you can reboot, shutdown, and upload numerous files to the Pi via a drag and drop interface. Simply select the emulator you want to upload files to, find your game file, and drag it onto the box. In a few moments, the file will be uploaded. Summary In this article, you have been introduced to PiPlay Raspberry Pi distribution. All Raspberry Pi distributions share a lot in common, they go about implementing gaming in their own unique ways. Try all and use the one that fits your gaming style the best. Resources for Article: Further resources on this subject: Testing Your Speed [article] Making the Unit Very Mobile – Controlling the Movement of a Robot with Legs [article] Clusters, Parallel Computing, and Raspberry Pi – A Brief Background [article]
Read more
  • 0
  • 0
  • 3409

article-image-overview-tdd
Packt
06 Nov 2015
11 min read
Save for later

Overview of TDD

Packt
06 Nov 2015
11 min read
 In this article, by Ravi Gupta, Harmeet Singh, and Hetal Prajapati, authors of the book Test-Driven JavaScript Development explain how testing is one of the most important phases in the development of any project, and in the traditional software development model. Testing is usually executed after the code for functionality is written. Test-driven development (TDD) makes a big difference by writing tests before the actual code. You are going to learn TDD for JavaScript and see how this approach can be utilized in the projects. In this article, you are going to learn the following: Complexity of web pages Understanding TDD Benefits of TDD and common myths (For more resources related to this topic, see here.) Complexity of web pages When Tim Berners-Lee wrote the first ever web browser around 1990, it was supposed to run HTML, neither CSS nor JavaScript. Who knew that WWW will be the most powerful communication medium? Since then, there are now a number of technologies and tools which help us write the code and run it for our needs. We do a lot these days with the help of the Internet. We shop, read, learn, share, and collaborate... well, a few words are not going to suffice to explain what we do on the Internet, are they? Over the period of time, our needs have grown to a very complex level, so is the complexity of code written for websites. It's not plain HTML anymore, not some CSS style, not some basic JavaScript tweaks. That time has passed. Pick any site you visit daily, view source by opening developer tools of the browser, and look at the source code of the site. What do you see? Too much code? Too many styles? Too many scripts? The JavaScript code and CSS code is so huge to keep it in as inline, and we need to keep them in different files, sometimes even different folders to keep them organized. Now, what happens before you publish all the code live? You test it. You test each line and see if that works fine. Well, that's a programmer's job. Zero defect, that's what every organization tries to achieve. When that is in focus, testing comes into picture, more importantly, a development style, which is essentially test driven. As the title says for this article, we're going to keep our focus on test-driven JavaScript development.   Understanding Test-driven development TDD, short for Test-driven development, is a process for software development. Kent Beck, who is known for development of TDD, refers this as "Rediscovery." Kent's answer to a question on Quora can be found at https://www.quora.com/Why-does-Kent-Beck-refer-to-the-rediscovery-of-test-driven-development. "The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output. After I'd written the first xUnit framework in Smalltalk I remembered reading this and tried it out. That was the origin of TDD for me. When describing TDD to older programmers, I often hear, "Of course. How else could you program?" Therefore I refer to my role as "rediscovering" TDD." If you go and try to find references to TDD, you would even get few references from 1968. It's not a new technique, though did not get so much attention yet. Recently, an interest toward TDD is growing, and as a result, there are a number of tools on the Web. For example, Jasmine, Mocha, DalekJS, JsUnit, QUnit, and Karma are among these popular tools and frameworks. More specifically, test-driven JavaScript development is getting popular these days. Test-driven development is a software development process, which enforces a developer to write test before production code. A developer writes a test, expects a behavior, and writes code to make the test pass. It is needless to mention that the test will always fail at the start. Need of testing To err is human. As a developer, it's not easy to find defects in our own code and often we think that our code is perfect. But there are always some chances that a defect is present in the code. Every organization or individual wants to deliver the best software they can. This is one major reason that every software, every piece of code is well tested before its release. Testing helps to detect and correct defects. There are a number of reasons why testing is needed. They are as follows: To check if the software is functioning as per the requirements There will not be just one device or one platform to run your software The end user will perform an action as a programmer you never expected There was a study conducted by National Institute of Standards and Technology (NIST) in 2002, which reported that software bugs cost the U.S. economy around $60 billion annually. With better testing, more than one-third of the cost could be avoided. The earlier the defect is found, the cheaper it is to fix it. A defect found post release would cost 10-100 times more to fix than if it had already been detected and fixed. The report of the study performed by NIST can be found at http://www.nist.gov/director/planning/upload/report02-3.pdf. If we draw a curve for the cost, it comes as an exponential when it comes to cost. The following figure clearly shows that the cost increases as the project matures with time. Sometimes, it's not possible to fix a defect without making changes in the architecture. In those cases, the cost, sometimes, is so much that developing the software from scratch seems like a better option. Benefits of TDD and common myths Every methodology has its own benefits and myths among people. The following sections will analyze the key benefits and most common myths of TDD. Benefits TDD has its own advantages over regular development approaches. There are a number of benefits, which help make a decision of using TDD over the traditional approach. Automated testing: If you did see a website code, you know that it's not easy to maintain and test all the scripts manually and keep them working. A tester may leave a few checks, but automated tests won't. Manual testing is error prone and slow. Lower cost of overall development: With TDD, the number of debugs is significantly decreased. You develop some code; run tests, if you fail, re-doing the development is significantly faster than debugging and fixing it. TDD aims at detecting defect and correcting them at an early stage, which costs much cheaper than detecting and correcting at a later stage or post release. Also, now debugging is very less frequent and significant amount of time is saved. With the help of tools/test runners like Karma, JSTestDriver, and so on, running every JavaScript tests on browser is not needed, which saves significant time in validation and verification while the development goes on. Increased productivity: Apart from time and financial benefits, TDD helps to increase productivity since the developer becomes more focused and tends to write quality code that passes and fulfills the requirement. Clean, maintainable, and flexible code: Since tests are written first, production code is often very neat and simple. When a new piece of code is added, all the tests can be run at once to see if anything failed with the change. Since we try to keep our tests atomic, and our methods also address a single goal, the code automatically becomes clean. At the end of the application development, there would be thousands of test cases which will guarantee that every piece of logic can be tested. The same test cases also act as documentation for users who are new to the development of system, since these tests act as an example of how the code works. Improved quality and reduced bugs: Complex codes invite bugs. Developers when change anything in neat and simple code, they tend to leave less or no bugs at all. They tend to focus on purpose and write code to fulfill the requirement. Keeps technical debt to minimum: This is one of the major benefits of TDD. Not writing unit tests and documentation is a big part, which increases technical debt for a software/project. Since TDD encourages you to write tests first, and if they are well written, they act as documentation, you keep technical debt for these to minimum. As Wikipedia says, A technical debt can be defined as tasks to be performed before a unit can be called complete. If the debt is not repaid, interest also adds up and makes it harder to make changes at a later stage. More about Technical debt can be found at https://en.wikipedia.org/wiki/Technical_debt. Myths Along with the benefits, TDD has some myths as well. Let's check few of them: Complete code coverage: TDD enforces to write tests first and developers write minimum amount of code to pass the test and almost 100% code coverage is done. But that does not guarantee that nothing is missed and the code is bug free. Code coverage tools do not cover all the paths. There can be infinite possibilities in loops. Of course it's not possible and feasible to check all the paths, but a developer is supposed to take care of major and critical paths. A developer is supposed to take care of business logic, flow, and process code most of the times. No need to test integration parts, setter-getter methods for properties, configurations, UI, and so on. Mocking and stubbing is to be used for integrations. No need of debugging the code: Though test-first development makes one think that debugging is not needed, but it's not always true. You need to know the state of the system when a test failed. That will help you to correct and write the code further. No need of QA: TDD cannot always cover everything. QA plays a very important role in testing. UI defects, integration defects are more likely to be caught by a QA. Even though developers are excellent, there are chances of errors. QA will try every kind of input and unexpected behavior that even a programmer did not cover with test cases. They will always try to crash the system with random inputs and discover defects. I can code faster without tests and can also validate for zero defect: While this may stand true for very small software and websites where code is small and writing test cases may increase overall time of development and delivery of the product. But for bigger products, it helps a lot to identify defects at a very early stage and gives a chance to correct at a very low cost. As seen in the previous screenshots of cost of fixing defects for phases and testing types, the cost of correcting a defect increases with time. Truly, whether TDD is required for a project or not, it depends on context. TDD ensures a good design and architecture: TDD encourages developers to write quality code, but it is not a replacement for good design practice and quality code. Will a team of developers be enough to ensure a stable and scalable architecture? Design should still be done by following the standard practices. You need to write all tests first: Another myth says that you need to write all tests first and then the actual production code. Actually, generally an iterative approach is used. Write some tests first, then some code, run the tests, fix the code, run the tests, write more tests, and so on. With TDD, you always test parts of software and keep developing. There are many myths, and covering all of them is not possible. The point is, TDD offers developers a better opportunity of delivering quality code. TDD helps organizations by delivering close to zero-defect products. Summary In this article, you learned about what TDD is. You learned about the benefits and myths of TDD. Resources for Article: Further resources on this subject: Understanding outside-in [article] Jenkins Continuous Integration [article] Understanding TDD [article]
Read more
  • 0
  • 0
  • 3409

article-image-customizing-prestashop-theme-part-1
Packt
22 Jul 2010
7 min read
Save for later

Customizing PrestaShop Theme Part 1

Packt
22 Jul 2010
7 min read
(For more resources on PrestaShop 1.3, see here.) The most basic level is using the back office panel to customize the layout. Using this knowledge, we can make some quick and easy changes without having any technical knowledge. If you need more advanced changes than what can be achieved here, you will need to edit the theme and the CSS files, which will be explained in the next article on Customizing PrestaShop Theme Part 2. It must be noted that all design changes that you can do in this back office can also be achieved through customization on the theme files (which involves editing of the file's markup) too. Although knowledge of this theme editing approach encased that of the back office setting, it is useful to know that there are reasons to choose the latter option with no "hacking" of scripts even if you are an advanced user as there could be some issues when you have to update to the next PrestaShop version. You will have to update some of these modified files as these changes may not be automatically included in the newer version. We have to decide what kind of layout we would want, just like the interior design space of a building that you are erecting, you need to visualize the spaces and how users will navigate your retail outlet. You will also need to know what kind of resources can help the successful function of your store, customers in real brick-and-mortar stores do not have to ask a lot of questions as they are prone to browsing the items while having the advantage of feeling, smelling, holding, or trying the items at the same time. While this is true for a real store/shop, the online store does not have this advantage. So, consider features/functions that can be a "replacement" to this disadvantage, such as a 30 day return policy. In a real shop, customers may ask questions at the customer service desks. The same thing can be done with your online store; you can add a lot of information that your customers may need while balancing it with a good design, navigation, and browsing experience. This will ensure that the customer finds the information and this reduces the need to repetitively answer the same queries. This is one of the main reasons why an online store exists, which means that information can be obtained easily 24x7. Therefore, in an online shop, you will have to decide on what kind of features you want to introduce, for example, one block for product information, another for customer service information where they can get information on return policy, how to make payment, and so on. This is just a background that is needed to decide the functions of your store. We will not be discussing about what makes a good navigation or whether one way can be more effective than another. We will learn about how you can use the knowledge about theming for PrestaShop-based stores to build your online store or if you are a web designer, your clients' online stores suitable with the stores' concepts. You will also learn how to go about in applying the necessary modules to complement your theme setup. Before we start this article, you should get acquainted with the back office panel. This will help you understand what we are exploring here. In this article, we will be sticking with the default PrestaShop theme and learn how to: Install, uninstall, enable, and disable module blocks in the center, left, and right columns. Transplant and position modules by moving them to columns and within the columns. The default layout Let's have a look again at your current storefront and how the theme is governed by the back office control panel. By looking at the screenshot, you can tell which back office items you need to modify, replace, or set according to your needs. The basic layout outline can be seen in the following screenshot: Besides the back office control over appearance, our theme is also affected by the modules that control the functionality of your store. At this stage, we will be working on the existing modules in PrestaShop. This is where you decide whether your site visitor will see the product categories, the top selling products, your product listing, the specials, your featured products, and so on. If you run an e-commerce store with a payment option that links automatically to a payment gateway, you may want to study a bit more about each of these modules as well. You will also notice that the default theme uses a three column layout with a header in the top block and a footer at the bottom. Through the back office panel, all the default blocks on the left and right columns can be moved or transplanted interchangeably. Some of the blocks in the header (top blocks) can be moved into the left column or right column. The featured product block and the editorial block, which are at the center column, are pretty much stuck in this position. Modules The Modules tab allows you to control the modules you want to use in the store. You will be able to transplant the modules and move them around according to the site navigation you want, considering some limitations at this stage. You can move them up or down in the columns. You may also position them in the left or the right column or you may disable them. You also have the option of adding a new module or choosing ones that are available from the PrestaStore. PrestaShop has some already installed modules, and the number of newly developed ones is growing every day. Now let's move on to Back Office | Modules, as shown in the following screenshot:     We will go into the listing and get some ideas on each one. However, we will focus in greater detail on the modules that affect theming directly. Among the existing modules in this version (PrestaShop 1.3.1), which are readily available for installation, some of them are: Advertisement – 1 module: Google Adsense. Products module – 6 modules: Cross selling, RSS products feed, Products Comments, Products Category, Product tooltips, Send to a Friend module. Stats Engines – 5 modules: Artichow, Google Chart, Visifire, XML/SWF Charts, ExtJS. Payment – 8 modules: Bank Wire, Cash on delivery (COD), Cheque, Google Checkout, Hipay, Moneybookers, Paypal, PaypalAPI. Tools – 14 modules (but only 12 modules listed): Birthday Present, Canonical URL, Home text editor, Customers follow-up, Google sitemap, Featured Products on the homepage, Customers loyalty and rewards, Mail alerts, Newsletter, Customer referral program, SMS Tm4b, and Watermark. Blocks – 23 modules: Block advertising, Top seller block, Cart block, Categories block, Currency block, Info block, Language block, Link block, Manufacturers block, My Account block, New products block, Newsletter block, Block payment logo, Permanent links block, RSS feed block, Quick Search block, Specials block, Suppliers block, Tags block, User info block, Footer links block, Viewed products block, Wish list block. Stats – 25 modules: Google Analytics, Pages not found, Search engine keywords, Best categories, Best customers, Best products, Best suppliers, Best vouchers, Carrier distribution, Catalog statistics v1.0, Catalog evaluation, Data mining for statistics, Geolocation, Condensed stats for the Back Office homepage, Visitors online, Newsletter, Visitors origin, Registered Customer Info, Product details, Customer accounts, Sales and orders, Shop search, Visits and Visitors, Tracking - Front office. You should also see an Icon legend on the right that reads the following: Apart from these three options of installing, enabling, and disabling, you may also add new modules using the button on the top-left corner of the module tab. There are also plenty of third party modules that can be used to make the store more interactive and attractive. Discussing about them is not within the scope of this article.
Read more
  • 0
  • 0
  • 3407

article-image-groovy-closures
Packt
16 Sep 2015
9 min read
Save for later

Groovy Closures

Packt
16 Sep 2015
9 min read
In this article by Fergal Dearle, the author of the book Groovy for Domain-Specific Languages - Second Edition, we will focus exclusively on closures. We will take a close look at them from every angle. Closures are the single most important feature of the Groovy language. Closures are the special seasoning that helps Groovy stand out from Java. They are also the single most powerful feature that we will use when implementing DSLs. In the article, we will discuss the following topics: We will start by explaining just what a closure is and how we can define some simple closures in our Groovy code We will look at how many of the built-in collection methods make use of closures for applying iteration logic, and see how this is implemented by passing a closure as a method parameter We will look at the various mechanisms for calling closures A handy reference that you might want to consider having at hand while you read this article is GDK Javadocs, which will give you full class descriptions of all of the Groovy built-in classes, but of particular interest here is groovy.lang.Closure. (For more resources related to this topic, see here.) What is a closure Closures are such an unfamiliar concept to begin with that it can be hard to grasp initially. Closures have characteristics that make them look like a method in so far as we can pass parameters to them and they can return a value. However, unlike methods, closures are anonymous. A closure is just a snippet of code that can be assigned to a variable and executed later: def flintstones = ["Fred","Barney"] def greeter = { println "Hello, ${it}" } flintstones.each( greeter ) greeter "Wilma" greeter = { } flintstones.each( greeter ) greeter "Wilma" Because closures are anonymous, they can easily be lost or overwritten. In the preceding example, we defined a variable greeter to contain a closure that prints a greeting. After greeter is overwritten with an empty closure, any reference to the original closure is lost. It's important to remember that greeter is not the closure. It is a variable that contains a closure, so it can be supplanted at any time. Because greeter has a dynamic type, we could have assigned any other object to it. All closures are a subclass of the type groovy.lang.Closure. Because groovy.lang is automatically imported, we can refer to Closure as a type within our code. By declaring our closures explicitly as Closure, we cannot accidentally assign a non-closure to them: Closure greeter = { println it } For each closure that is declared in our code, Groovy generates a Closure class for us, which is a subclass of groovy.lang.Closure. Our closure object is an instance of this class. Although we cannot predict what exact type of closure is generated, we can rely on it being a subtype of groovy.lang.Closure. Closures and collection methods We will encounter Groovy lists and see some of the iteration functions, such as the each method: def flintstones = ["Fred","Barney"] flintstones.each { println "Hello, ${it}" } This looks like it could be a specialized control loop similar to a while loop. In fact, it is a call to the each method of Object. The each method takes a closure as one of its parameters, and everything between the curly braces {} defines another anonymous closure. Closures defined in this way can look quite similar to code blocks, but they are not the same. Code defined in a regular Java or Groovy style code block is executed as soon as it is encountered. With closures, the block of code defined in the curly braces is not executed until the call() method of the closure is made: println "one" def two = { println "two" } println "three" two.call() println "four" Will print the following: one three two four Let's dig a bit deeper into the structure of the each of the calls shown in the preceding code. I refer to each as a call because that's what it is—a method call. Groovy augments the standard JDK with numerous helper methods. This new and improved JDK is referred to as the Groovy JDK, or GDK for short. In the GDK, Groovy adds the each method to the java.lang.Object class. The signature of the each method is as follows: Object each(Closure closure) The java.lang.Object class has a number of similar methods such as each, find, every, any, and so on. Because these methods are defined as part of Object, you can call them on any Groovy or Java object. They make little sense on most objects, but they do something sensible if not very useful: given: "an Integer" def number = 1 when: "we call the each method on it" number.each { println it } then: "just the object itself gets passed into the Closure" "1" == output() These methods all have specific implementations for all of the collection types, including arrays, lists, ranges, and maps. So, what is actually happening when we see the call to flintstones.each is that we are calling the list's implementation of the each method. Because each takes a Closure as its last and only parameter, the following code block is interpreted by Groovy as an anonymous Closure object to be passed to the method. The actual call to the closure passed to each is deferred until the body of the each method itself is called. The closure may be called multiple times—once for every element in the collection. Closures as method parameters We already know that parentheses around method parameters are optional, so the previous call to each can also be considered equivalent to: flintstones.each ({ println "Hello, ${it}") Groovy has a special handling for methods whose last parameter is a closure. When invoking these methods, the closure can be defined anonymously after the method call parenthesis. So, yet another legitimate way to call the preceding line is: flintstones.each() { println "hello, ${it}" } The general convention is not to use parentheses unless there are parameters in addition to the closure: given: def flintstones = ["Fred", "Barney", "Wilma"] when: "we call findIndexOf passing int and a Closure" def result = flintstones.findIndexOf(0) { it == 'Wilma'} then: result == 2 The signature of the GDK findIndexOf method is: int findIndexOf(int, Closure) We can define our own methods that accept closures as parameters. The simplest case is a method that accepts only a single closure as a parameter: def closureMethod(Closure c) { c.call() } when: "we invoke a method that accepts a closure" closureMethod { println "Closure called" } then: "the Closure passed in was executed" "Closure called" == output() Method parameters as DSL This is an extremely useful construct when we want to wrap a closure in some other code. Suppose we have some locking and unlocking that needs to occur around the execution of a closure. Rather than the writer of the code to locking via a locking API call, we can implement the locking within a locker method that accepts the closure: def locked(Closure c) { callToLockingMethod() c.call() callToUnLockingMethod() } The effect of this is that whenever we need to execute a locked segment of code, we simply wrap the segment in a locked closure block, as follows: locked { println "Closure called" } In a small way, we are already writing a mini DSL when we use these types on constructs. This call to the locked method looks, to all intents and purposes, like a new language construct, that is, a block of code defining the scope of a locking operation. When writing methods that take other parameters in addition to a closure, we generally leave the Closure argument to last. As already mentioned in the previous section, Groovy has a special syntax handling for these methods, and allows the closure to be defined as a block after the parameter list when calling the method: def closureMethodInteger(Integer i, Closure c) { println "Line $i" c.call() } when: "we invoke a method that accepts an Integer and a Closure" closureMethodInteger(1) { println "Line 2" } then: "the Closure passed in was executed with the parameter" """Line 1 Line 2""" == output() Forwarding parameters Parameters passed to the method may have no impact on the closure itself, or they may be passed to the closure as a parameter. Methods can accept multiple parameters in addition to the closure. Some may be passed to the closure, while others may not: def closureMethodString(String s, Closure c) { println "Greet someone" c.call(s) } when: "we invoke a method that accepts a String and a Closure" closureMethodString("Dolly") { name -> println "Hello, $name" } then: "the Closure passed in was executed with the parameter" """Greet someone Hello, Dolly""" == output() This construct can be used in circumstances where we have a look-up code that needs to be executed before we have access to an object. Say we have customer records that need to be retrieved from a database before we can use them: def withCustomer (id, Closure c) { def cust = getCustomerRecord(id) c.call(cust) } withCustomer(12345) { customer -> println "Found customer ${customer.name}" } We can write an updateCustomer method that saves the customer record after the closure is invoked, and amend our locked method to implement transaction isolation on the database, as follows: class Customer { String name } def locked (Closure c) { println "Transaction lock" c.call() println "Transaction release" } def update (customer, Closure c) { println "Customer name was ${customer.name}" c.call(customer) println "Customer name is now ${customer.name}" } def customer = new Customer(name: "Fred") At this point, we can write code that nests the two method calls by calling update as follows: locked { update(customer) { cust -> cust.name = "Barney" } } This outputs the following result, showing how the update code is wrapped by updateCustomer, which retrieves the customer object and subsequently saves it. The whole operation is wrapped by locked, which includes everything within a transaction: Transaction lock Customer name was Fred Customer name is now Barney Transaction release Summary In this article, we covered closures in some depth. We explored the various ways to call a closure and the means of passing parameters. We saw how we can pass closures as parameters to methods, and how this construct can allow us to appear to add mini DSL syntax to our code. Closures are the real "power" feature of Groovy, and they form the basis of most of the DSLs. Resources for Article: Further resources on this subject: Using Groovy Closures Instead of Template Method [article] Metaprogramming and the Groovy MOP [article] Clojure for Domain-specific Languages - Design Concepts with Clojure [article]
Read more
  • 0
  • 0
  • 3406
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-creating-your-infrastructure-using-chef-provisioning
Packt
05 Jun 2015
5 min read
Save for later

Creating your infrastructure using Chef Provisioning

Packt
05 Jun 2015
5 min read
In this article by Matthias Marschall, author of the book Chef Infrastructure Automation Cookbook - Second Edition, we will "know how to use Chef to manage the software on individual machines and you know how to use knife to bootstrap individual nodes. Chef Provisioning helps you to use the power of Chef to create your whole infrastructure for you. No matter whether you want to create a cluster of Vagrant boxes, Docker instances, or Cloud servers, Chef Provisioning lets you define your infrastructure in a simple recipe and run it idempotently. Let's see how to create a Vagrant machine using a Chef recipe. (For more resources related to this topic, see here.) Getting ready Make sure that you have your Berksfile, my_cookbook and web_server roles ready to create an nginx site. How to do it... Let's see how "to create a Vagrant machine and install nginx "on it: Describe your Vagrant machine in a recipe called mycluster.rb: mma@laptop:~/chef-repo $ subl mycluster.rb require 'chef/provisioning'   with_driver 'vagrant' with_machine_options :vagrant_options => { 'vm.box' => 'opscode-ubuntu-14.04' }   machine 'web01' do role 'web_server' end Install all required cookbooks in your local chef-repo: mma@laptop:~/chef-repo $ berks installmma@laptop:~/chef-repo $ berks vendor cookbooks Resolving cookbook dependencies... Using apt (2.6.1) ...TRUNCATED OUTPUT... Vendoring yum-epel (0.6.0) to cookbooks/yum-epel Run the Chef client in local mode to bring up the Vagrant machine and execute a Chef run on it: mma@laptop:~/chef-repo $ chef-client -z mycluster.rb [2015-03-08T21:09:39+01:00] INFO: Starting chef-zero on host localhost, port 8889 with repository at repository at /Users/mma/work/chef-repo ...TRUNCATED OUTPUT... Recipe: @recipe_files::/Users/mma/work/chef-repo/mycluster.rb * machine[webserver] action converge[2015-03-08T21:09:43+01:00] INFO: Processing machine[web01] action converge (@recipe_files::/Users/mma/work/chef-repo/mycluster.rb line 6) ...TRUNCATED OUTPUT... [2015-03-08T21:09:47+01:00] INFO: Executing sudo chef-client -l info on vagrant@127.0.0.1      [web01] [2015-03-08T20:09:21+00:00] INFO: Forking chef instance to converge...                Starting Chef Client, version 12.1.0                ...TRUNCATED OUTPUT...                Chef Client finished, 18/25 resources updated in 73.839065458 seconds ...TRUNCATED OUTPUT... [2015-03-08T21:11:05+01:00] INFO: Completed chef-client -l info on vagrant@127.0.0.1: exit status 0    - run 'chef-client -l info' on web01 [2015-03-08T21:11:05+01:00] INFO: Chef Run complete in 82.948293 seconds ...TRUNCATED OUTPUT... Chef Client finished, 1/1 resources updated in 85.914979 seconds Change" into the directory where Chef put the Vagrant configuration: mma@laptop:~/chef-repo $ cd ~/.chef/vms Validate that there is a Vagrant machine named web01 running: mma@laptop:~/.chef/vms $ vagrant status Current machine states: web01                 running (virtualbox) Validate that nginx is installed and running on the Vagrant machine: mma@laptop:~/.chef/vms $ vagrant ssh vagrant@web01:~$ wget localhost:80 ...TRUNCATED OUTPUT... 2015-03-08 22:14:45 (2.80 MB/s) - 'index.html' saved [21/21] How it works... Chef Provisioning comes with a selection of drivers for all kinds of infrastructures, including Fog (supporting Amazon EC2, OpenStack, and others), VMware VSphere, Vagrant (supporting Virtualbox and VMware Fusion), various Containers, such as LXC Docker "and Secure Shell (SSH). In this recipe, we make sure that we can use the directives provided by Chef Provisioning by requiring chef/provisioning library. Then, we configure the driver that we want to use. We use Vagrant and tell Chef to use the opscode-ubuntu-14.04 Vagrant box to spin up our machine. Using the machine resource, we ask Chef to spin up a Vagrant machine and configure it using Chef by applying the role web_server. The web_server role uses the cookbook my_cookbook to configure the newly created Vagrant machine. To make sure that all the required cookbooks are available to Chef, we use berks install and berks vendor cookbooks. The berks vendor cookbooks installs all the required cookbooks in the local cookbooks directory. The Chef client can access the cookbooks here, without the need for a Chef server. Finally, we use the Chef client to execute our Chef Provisioning recipe. It will spin up the defined Vagrant machine and execute a Chef client run on it. Chef Provisioning will put the Vagrant Virtual Machine (VM) definition into the directory ~/.chef/vms. To manage the Vagrant VM, you need to change to this directory. There's more... Instead of using the with_driver directive, you can use the CHEF_DRIVER environment variable: mma@laptop:~/chef-repo $ CHEF_DRIVER=vagrant chef-client -z mycluster.rb You can create multiple instances of a machine by using the machine_image directive in your recipe: machine_image 'web_server' do role 'web_server' end 1.upto(2) do |i| machine "web0#{i}" do    from_image 'web_server'   end end See also Find the source code of the Chef Provisioning library at GitHub: https://github.com/chef/chef-provisioning Find" the Chef Provisioning documentation at https://docs.chef.io/provisioning.html Learn how to" set up a Chef server using Chef Provisioning: https://www.chef.io/blog/2014/12/15/sysadvent-day-14-using-chef-provisioning-to-build-chef-server/ Summary This article deals with networking and applications spanning multiple servers. You learned how to create your whole infrastructure using Chef provisioning. Resources for Article: Further resources on this subject: Chef Infrastructure [article] Going Beyond the Basics [article] Getting started with using Chef [article]
Read more
  • 0
  • 0
  • 3405

article-image-text-mining-r-part-1
Robi Sen
16 Mar 2015
7 min read
Save for later

Text Mining with R: Part 1

Robi Sen
16 Mar 2015
7 min read
R is rapidly becoming the platform of choice for programmers, scientists, and others who need to perform statistical analysis and data mining. In part this is because R is incredibly easy to learn and with just a few commands you can perform data mining and analysis functions that would be very hard in more general purpose languages like Ruby, .Net, Java, or C++. To demonstrate R’s ease, flexibility, and power we will look at how to use R to look at a collection of tweets from the 2014 super bowl, clear up data via R, turn that data it a document matrix so we can analyze the data, then create a “word cloud” so we can visualize our analysis to look for interesting words. Getting Started To get started you need to download both R and R studio. R can be found here and RStudio can be found here. R and RStudio are available for most major operating systems and you should follow the up to date installation guides on their respective websites. For this example we are going to be using a data set from Techtunk which is rather large. For this article I have taken a small excerpt of techtrunks SuperBowl 2014, over 8 million tweets, and cleaned it up for the article. You can download it from the original data source here. Finally you will need to install the R packages text mining package (tm ) and word cloud package (wordcloud). You can use standard library method to install the packages or just use RStudio to install the packets. Preparing our Data As already stated you can find the total SuperBowl 2014 dataset. That being said, it's very large and broken up into many sets of Pipe Delimited files, and they have the .csv file extension but are not .csv, which can be somewhat awkward to work with. This though is a common problem when working with large data sets. Luckily the data set is broken up into fragments in that usually when you are working with large datasets you do not want to try to start developing against the whole data set rather a small and workable dataset the will let you quickly develop your scripts without being so large and unwieldy that it delays development. Indeed you will find that working the large files provided by Techtunk can take 10’s of minutes to process as is. In cases like this is good to look at the data, figure out what data you want, take a sample set of data, massage it as needed, and then work in it from there until you have your coding working exactly how you want. In our cases I took a subset of 4600 tweets from one of the pipe delimited files, converted the file format to Commas Separated Value, .csv, and saved it as a sample file to work from. You can do the same thing, you should consider using files smaller than 5000 records, however you would like or use the file created for this post here. Visualizing our Data For this post all we want to do is get a general sense of what the more common words are that are being tweeted during the superbowl. A common way to visualize this is with a word cloud which will show us the frequency of a term by representing it in greater size to other words in comparison to how many times it is mentioned in the body of tweets being analyzed. To do this we need to a few things first with our data. First we need to create read in our file and turn our collection of tweets into a Corpus. In general a Corpus is a large body of text documents. In R’s textming package it’s an object that will be used to hold our tweets in memory. So to load our tweets as a corpus into R you can do as shown here: # change this file location to suit your machine file_loc <- "yourfilelocation/largerset11.csv" # change TRUE to FALSE if you have no column headings in the CSV myfile <- read.csv(file_loc, header = TRUE, stringsAsFactors=FALSE) require(tm) mycorpus <- Corpus(DataframeSource(myfile[c("username","tweet")])) You can now simply print your Corpus to get a sense of it. > print(mycorpus) <<VCorpus (documents: 4688, metadata (corpus/indexed): 0/0)>> In this case, VCorpus is an automatic assignment meaning that the Corpus is a Volatile object stored in memory. If you want you can make the Corpus permanent using PCorpus. You might do this if you were doing analysis on actual documents such as PDF’s or even databases and in this case R makes pointers to the documents instead of full document structures in memory. Another method you can use to look at your corpus is inspect() which provides a variety of ways to look at the documents in your corpus. For example using: inspect(mycorpus[1,2]) This might give you a result like: > inspect(mycorpus[1:2]) <<VCorpus (documents: 2, metadata (corpus/indexed): 0/0)>> [[1]] <<PlainTextDocument (metadata: 7)>> sstanley84 wow rt thestanchion news fleury just made fraudulent investment karlsson httptco5oi6iwashg [[2]] <<PlainTextDocument (metadata: 7)>> judemgreen 2 hour wait train superbowl time traffic problemsnice job chris christie As such inspect can be very useful in quickly getting a sense of data in your corpus without having to try to print the whole corpus. Now that we have our corpus in memory let's clean it up a little before we do our analysis. Usually you want to do this on documents that you are analyzing to remove words that are not relevant to your analysis such as “stopwords” or words such as and, like, but, if, the, and the like which you don’t care about. To do this with the textmining package you want to use transforms. Transforms essentially various functions to all documents in a corpus and that the form of tm_map(your corpus, some function). For example we can use tm_map like this: mycorpus <- tm_map(mycorpus, removePunctuation) Which will now remove all the punctuation marks from our tweets. We can do some other transforms to clean up our data by converting all the text to lower case, removing stop words, extra whitespace, and the like. mycorpus <- tm_map(mycorpus, removePunctuation) mycorpus <- tm_map(mycorpus, content_transformer(tolower)) mycorpus <- tm_map(mycorpus, stripWhitespace) mycorpus <- tm_map(mycorpus, removeWords, c(stopwords("english"), "news")) Note the last line. In that case we are using the stopwords() method but also adding our own word to it; news. You could append your own list of stopwords in this manner. Summary In this post we have looked at the basics of doing text mining in R by selecting data, preparing it, cleaning, then performing various operations on it to visualize that data. In the next post, Part 2, we look at a simple use case showing how we can derive real meaning and value from a visualization by seeing how a simple word cloud and help you understand the impact of an advertisement. About the author Robi Sen, CSO at Department 13, is an experienced inventor, serial entrepreneur, and futurist whose dynamic twenty-plus year career in technology, engineering, and research has led him to work on cutting edge projects for DARPA, TSWG, SOCOM, RRTO, NASA, DOE, and the DOD. Robi also has extensive experience in the commercial space, including the co-creation of several successful start-up companies. He has worked with companies such as UnderArmour, Sony, CISCO, IBM, and many others to help build out new products and services. Robi specializes in bringing his unique vision and thought process to difficult and complex problems allowing companies and organizations to find innovative solutions that they can rapidly operationalize or go to market with.
Read more
  • 0
  • 0
  • 3404

article-image-installing-and-using-sametime-connect
Packt
04 Oct 2010
6 min read
Save for later

Installing and Using Sametime Connect

Packt
04 Oct 2010
6 min read
  IBM Lotus Sametime 8 Essentials: A User's Guide Mastering Online Enterprise Communication with this collaborative software Collaborate securely with your colleagues and teammates both inside and outside your organization by using Sametime features such as instant messaging and online meetings Make your instant messaging communication more interesting with the inclusion of graphics, images, and emoticons to convey more information in fewer words Communicate with other instant messaging services and users, such as AOL Instant Messaging, Yahoo Instant Messaging, and Google Talk and know how someone's online status can help you communicate faster and more efficiently Discover how the Sametime Meeting Center can maximize the productivity of teams in your organization with the use of online meetings, training session playback, seamless voice/video integration, and screen sharing See how Sametime works in common, every-day, real-world situations with tips, resources, and detailed screenshots Read more about this book (For more resources on IBM, see here.) Installing Sametime Connect on Windows Installing Sametime Connect on a Windows desktop is similar to installing any other Windows software. In order to run Sametime your workstation will need to meet the minimum hardware and operating system requirements. If you're unsure about your hardware or operating system, be sure to check with your system administrator. You'll need a copy of the installation software, which is typically a file that ends in .EXE. Locate the file via Windows Explorer, and begin the installation by double-clicking on the setup.exe file. After a language option screen, you will see the Sametime Connect client installation welcome screen to start your install process. Click on Next to proceed. After a License screen (in which you select the I Accept option and click on Next), you will have the choice of where your install of Sametime Connect should be placed: You will see one final screen to confirm you are ready to start your install: If everything seems correct, click on the Install button to start the process. The Windows installer will run for a few minutes, and will successfully install the software in the location you have specified. Once it has installed, you will see a message telling you the installation was successful, and also offering to launch the Sametime Connect software for you: Assuming you leave the Launch option selected, Sametime Connect will start and take you to the Sametime sign on screen. Installing Sametime Connect on a Macintosh Mac users can also install Sametime Connect. That's one really nice feature of the Sametime Connect client—you have options as to which operating system you can use. So if you use Windows at work, but have a Mac at home, you can still stay connected to your Sametime buddies. And as with the Windows environment, your Macintosh will need to meet the minimum hardware and operating system requirements in order to run Sametime. We've listed them here. The following versions of the Macintosh operating system can run the Sametime Connect client: OSX 10.4.x and OSX 10.5. To install the Mac Sametime Connect client, you will need the sametime-connect.pkg file or the file specific to the version of Sametime supported in your environment. You begin by clicking on the .pkg file which will launch the Sametime installer. Click on Continue to proceed through the license and language agreements until you reach the screen to choose the install directory. You can choose to install Sametime in a directory other than the default, but the default is usually a good choice. Once you've decided on the install location, click on Install to proceed. If your install is successful, you'll see the following screen. You'll also see a Sametime icon in your applications folder on the Mac. Installing Sametime Connect on Linux Installing Sametime Connect on a Linux desktop is just as easy as installing Sametime Connect on any other desktop. We've included the minimum hardware and operating system requirements as follows: You'll need a copy of the installation software, typically a file that ends with an .RPM suffix. Here is an example of what it looks like on a SuSE Linux desktop: Double-click on the sametime-connect-8.0.2-1.i586.rpm file to start the installation. A dialog box appears listing the name of the software that will be installed, along with a checkmark next to it to specify that it's the correct item. When you're ready, click on the Install button to start the process: The installer will run for a few minutes and come back with a message saying the installation was successful. Once that is done, all that's left to do is to launch Sametime Connect from your desktop application menu: When Sametime launches for the very first time, you'll see the Sametime splash screen and you'll be required to respond to the licensing agreement dialog box. Type 1 to accept the agreement or press Enter to read the license agreement. Once you have agreed to the licensing agreement, the sign-on screen for the Sametime Connect client will be displayed. At that point, you will have the sign-on screen for the Connect client, and it will work just like any other version of Sametime Connect. Setting up the connection to the Sametime server Now that you have Sametime installed, you'll need to log into it. You will have the Sametime icon on your desktop or in your start menu, depending on the operating system you are using. Launching Sametime will open up the logon dialog box: A few essential pieces of information are needed to complete this dialog box, which they should be provided to you by your technical department, namely Host server, User name, and Password. The Host server field is the Sametime server name. As your contacts connect to this server, you can see when they are available for chatting by the status icons that appear by their names. Your username is normally the same name or user id you use to sign on to your Lotus Notes client, but you may have a separate user id for Sametime depending on the type of authentication Sametime is using. Your password is most likely the same as your Notes client id password, but your technical department should provide you with this information. If you want to automatically logon when you start up Sametime, select the Remember Password and Automatically log in checkboxes. This combination ensures that you will automatically sign into Sametime whenever you start up the application. And while this says "automatically", it's important to remember to keep your password up-to-date. The password in the dialog box will require an update for your login to Sametime to be successful. Once you have completed the dialog box, click on Log In, and if your login information is correct, your Sametime client will show you connected to the server:
Read more
  • 0
  • 0
  • 3404

article-image-new-features-jpa-20
Packt
28 Jul 2010
9 min read
Save for later

New Features in JPA 2.0

Packt
28 Jul 2010
9 min read
(For more resources on Java, see here.) Version 2.0 of the JPA specification introduces some new features to make working with JPA even easier. In the following sections, we discuss some of these new features: Criteria API One of the main additions to JPA in the 2.0 specification is the introduction of the Criteria API. The Criteria API is meant as a complement to the Java Persistence Query Language (JPQL). Although JPQL is very flexible, it has some problems that make working with it more difficult than necessary. For starters, JPQL queries are stored as strings and the compiler has no way of validating JPQL syntax. Additionally, JPQL is not type safe. We could write a JPQL query in which our where clause could have a string value for a numeric property and our code would compile and deploy just fine. To get around the JPQL limitations described in the previous paragraph, the Criteria API was introduced to JPA in version 2.0 of the specification. The Criteria API allows us to write JPA queries programmatically, without having to rely on JPQL. The following code example illustrates how to use the Criteria API in our Java EE 6 applications: package net.ensode.glassfishbook.criteriaapi;import java.io.IOException;import java.io.PrintWriter;import java.util.List;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.PersistenceUnit;import javax.persistence.TypedQuery;import ja vax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Path;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import javax.persistence.metamodel.EntityType;import javax.persistence.metamodel.Metamodel;import javax.persistence.metamodel.SingularAttribute;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(urlPatterns = {"/criteriaapi"})public class CriteriaApiDemoServlet extends HttpServlet{ @PersistenceUnit(unitName = "customerPersistenceUnit") private EntityManagerFactory entityManagerFactory; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter printWriter = response.getWriter(); List<UsState> matchingStatesList; EntityManager entityManager = entityManagerFactory.createEntityManager(); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<UsState> criteriaQuery = criteriaBuilder.createQuery(UsState.class); Root<UsState> root = criteriaQuery.from(UsState.class); Metamodel metamodel = entityManagerFactory.getMetamodel(); EntityType<UsState> usStateEntityType = metamodel.entity(UsState.class); SingularAttribute<UsState, String> usStateAttribute = usStateEntityType.getDeclaredSingularAttribute("usStateNm", String.class); Path<String> path = root.get(usStateAttribute); Predicate predicate = criteriaBuilder.like(path, "New%"); criteriaQuery = criteriaQuery.where(predicate); TypedQuery typedQuery = entityManager.createQuery(criteriaQuery); matchingStatesList = typedQuery.getResultList(); response.setContentType("text/html"); printWriter.println("The following states match the criteria:<br/>"); for (UsState state : matchingStatesList) { printWriter.println(state.getUsStateNm() + "<br/>"); } }} This example takes advantage of the Criteria APIc. When writing code using the Criteria API, the first thing we need to do is to obtain an instance of a class implementing the javax.persistence.criteria. CriteriaBuilder interface. As we can see in the previous example, we need to obtain said instance by invoking the getCriteriaBuilder() method on our EntityManager. From our CriteriaBuilder implementation, we need to obtain an instance of a class implementing the javax.persistence.criteria.CriteriaQuery interface. We do this by invoking the createQuery() method in our CriteriaBuilder implementation. Notice that CriteriaQuery is generically typed. The generic type argument dictates the type of result that our CriteriaQuery implementation will return upon execution. By taking advantage of generics in this way, the Criteria API allows us to write type safe code. Once we have obtained a CriteriaQuery implementation, from it we can obtain an instance of a class implementing the javax.persistence.criteria.Root interface. The Root implementation dictates what JPA entity we will be querying from. It is analogous to the FROM query in JPQL (and SQL). The next two lines in our example take advantage of another new addition to the JPA specification—the Metamodel API. In order to take advantage of the Metamodel API, we need to obtain an implementation of the javax.persistence. metamodel.Metamodel interface by invoking the getMetamodel() method on our EntityManagerFactory. From our Metamodel implementation, we can obtain a generically typed instance of the javax.persistence.metamodel.EntityType interface. The generic type argument indicates the JPA entity our EntityType implementation corresponds to. EntityType allows us to browse the persistent attributes of our JPA entities at runtime. This is exactly what we do in the next line in our example. In our case, we are getting an instance of SingularAttribute, which maps to a simple, singular attribute in our JPA entity. EntityType has methods to obtain attributes that map to collections, sets, lists, and maps. Obtaining these types of attributes is very similar to obtaining a SingularAttribute, therefore we won't be covering those directly. Refer to the Java EE 6 API documentation at http://java.sun.com/javaee/6/ docs/api/ for more information. As we can see in our example, SingularAttribute contains two generic type arguments. The first argument dictates the JPA entity we are working with and the second one indicates the type of attribute. We obtain our SingularAttribute by invoking the getDeclaredSingularAttribute() method on our EntityType implementation and passing the attribute name (as declared in our JPA entity) as a String. Once we have obtained our SingularAttribute implementation, we need to obtain an import javax.persistence.criteria.Path implementation by invoking the get() method in our Root instance and passing our SingularAttribute as a parameter. In our example, we will get a list of all the "new" states in the United States (that is, all states whose names start with "New"). Of course, this is the job of a "like" condition. We can do this with the Criteria API by invoking the like() method on our CriteriaBuilder implementation. The like() method takes our Path implementation as its first parameter and the value to search for as its second parameter. CriteriaBuilder has a number of methods that are analogous to SQL and JPQL clauses such as equals(), greaterThan(), lessThan(), and(), or(), and so on and so forth (for the complete list, refer to the Java EE 6 documentation at http://java.sun.com/javaee/6/docs/api/). These methods can be combined to create complex queries via the Criteria API. The like() method in CriteriaBuilder returns an implementation of the javax.persistence.criteria.Predicate interface, which we need to pass to the where() method in our CriteriaQuery implementation. This method returns a new instance of CriteriaBuilder which we assign to our criteriaBuilder variable. At this point, we are ready to build our query. When working with the Criteria API, we deal with the javax.persistence.TypedQuery interface, which can be thought of as a type-safe version of the Query interface we use with JPQL. We obtain an instance of TypedQuery by invoking the createQuery() method in EntityManager and passing our CriteriaQuery implementation as a parameter. To obtain our query results as a list, we simply invoke getResultList() on our TypedQuery implementation. It is worth reiterating that the Criteria API is type safe. Therefore, attempting to assign the results of getResultList() to a list of the wrong type would result in a compilation error. After building, packaging, and deploying our code, then pointing the browser to our servlet's URL, we should see all the "New" states displayed in the browser. Bean Validation support Another new feature introduced in JPA 2.0 is support for JSR 303, Bean Validation. Bean Validation support allows us to annotate our JPA entities with Bean Validation annotations. These annotations allow us to easily validate user input and perform data sanitation. Taking advantage of Bean Validation is very simple, all we need to do is annotate our JPA entity fields or getter methods with any of the validation annotations defined in the javax.validation.constraints package. Once our fields are annotated as appropriate, the EntityManager will prevent non-validating data from being persisted. The following code example is a modified version of the Customer JPA entity. It has been modifed to take advantage of Bean Validation in some of its fields. package net.ensode.glassfishbook.jpa.beanvalidation;import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;@Entity@Table(name = "CUSTOMERS")public class Customer implements Serializable{ @Id @Column(name = "CUSTOMER_ID") private Long customerId; @Column(name = "FIRST_NAME") @NotNull @Size(min=2, max=20) private String firstName; @Column(name = "LAST_NAME") @NotNull @Size(min=2, max=20) private String lastName; private String email; public Long getCustomerId() { return customerId; } public void setCustomerId(Long customerId) { this.customerId = customerId; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; }} In this example, we used the @NotNull annotation to prevent the firstName and lastName of our entity from being persisted with null values. We also used the @Size annotation to restrict the minimum and maximum length of these fields. This is all we need to do to take advantage of Bean Validation in JPA. If our code attempts to persist or update an instance of our entity that does not pass the declared validation, an exception of type javax.validation.ConstraintViolationException will be thrown and the entity will not be persisted. As we can see, Bean Validation pretty much automates data validation, freeing us from having to manually write validation code. In addition to the two annotations discussed in the previous example, the javax.validation.constraints package contains several additional annotations that we can use to automate validation on our JPA entities. Refer to the Java EE 6 API documentation at http://java.sun.com/javaee/6/docs/api/ for the complete list. Summary In this article, we discussed some new JPA 2.0 features such as the Criteria API that allows us to build JPA queries programmatically, the Metamodel API that allows us to take advantage of Java's type safety when working with JPA, and Bean Validation that allows us to easily validate input by simply annotating our JPA entity fields. Further resources on this subject: Interacting with Databases through the Java Persistence API [article] Setting up GlassFish for JMS and Working with Message Queues [article]
Read more
  • 0
  • 0
  • 3403
article-image-importance-securing-web-services
Packt
23 Jul 2014
10 min read
Save for later

The Importance of Securing Web Services

Packt
23 Jul 2014
10 min read
(For more resources related to this topic, see here.) In the upcoming sections of this article we are going to briefly explain several concepts about the importance of securing web services. The importance of security The management of securities is one of the main aspects to consider when designing applications. No matter what, neither the functionality nor the information of organizations can be exposed to all users without any kind of restriction. Suppose the case of a human resource management application that allows you to consult wages of their employees, for example, if the company manager needs to know the salary of one of their employees, it is not something of great importance. But in the same context, imagine that one of the employees wants to know the salary of their colleagues, if access to this information is completely open, it could generate problems among employees with varied salaries. Security management options Java provides some options for security management. Right now we will explain some of them and demonstrate how to implement them. All authentication methods are practically based on credentials delivery from the client to the server. In order to perform this, there are several methods: BASIC authentication DIGEST authentication CLIENT CERT authentication Using API keys The Security Management in applications built with Java including those ones with RESTful web services, always rely on JAAS. Basic authentication by providing user credentials Possibly one of the most used techniques in all kind of applications. The user, before gaining functionality over the application is requested to enter a username and password both are validated in order to verify if credentials are correct (belongs to an application user). We are 99 percent sure you have performed this technique at least once, maybe through a customized mechanism, or if you used JEE platform, probably through JAAS. This kind of control is known as basic authentication. In order to have a working example, let’s start our application server JBoss AS 7, then go to bin directory and execute the file add-user.bat (.sh file for UNIX users). Finally, we will create a new user as follows: As a result, we will have a new user in JBOSS_HOME/standalone/configuration/application - users.properties file. JBoss is already set with a default security domain called other; the same one uses the information stored in the file we mentioned earlier in order to authenticate. Right now we are going to configure the application to use this security domain, inside the folder WEB-INF from resteasy-examples project, let's create a file named jboss-web.xml with the following content: <?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>other</security-domain> </jboss-web> Alright, let's configure the file web.xml in order to aggregate the securities constraints. In the following block of code, you will see on bold what you should add: <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xsi_schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <!-- Roles --> <security-role> <description>Any rol </description> <role-name>*</role-name> </security-role> <!-- Resource / Role Mapping --> <security-constraint> <display-name>Area secured</display-name> <web-resource-collection> <web-resource-name>protected_resources</web-resource-name> <url-pattern>/services/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description>User with any role</description> <role-name>*</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> </login-config> </web-app> From a terminal let's go to the home folder of the resteasy-examples project and execute mvn jboss-as:redeploy. Now we are going to test our web service as we did earlier by using SoapUI. We are going to perform request using the POST method to the URL SOAP UI shows us the HTTP 401 error; this means that the request wasn't authorized. This is because we performed the request without delivering the credentials to the server. Digest access authentication This authentication method makes use of a hash function to encrypt the password entered by the user before sending it to the server. This makes it obviously much safer than the BASIC authentication method, in which the user’s password travels in plain text that can be easily read by whoever intercepts. To overcome such drawbacks, digest MD5 authentication applies a function on the combination of the values of the username, realm of application security, and password. As a result we obtain an encrypted string that can hardly be interpreted by an intruder. Now, in order to perform what we explained before, we need to generate a password for our example user. And we have to generate it using the parameters we talked about earlier; username, realm, and password. Let’s go into the directory of JBOSS_HOME/modules/org/picketbox/main/ from a terminal and type the following: java -cp picketbox-4.0.7.Final.jar org.jboss. security.auth.callback.RFC2617Digest username MyRealmName password We will obtain the following result: RFC2617 A1 hash: 8355c2bc1aab3025c8522bd53639c168 Through this process we obtain the encrypted password, and use it in our password storage file (the JBOSS_HOME/standalone/configuration/application-users.properties). We must replace the password in the file and it will be used for the user username. We have to replace it because the old password doesn't contain the realm name information of the application. Next, We have to modify the web.xml file in the tag auth-method and change the value FORM to DIGEST, and we should set the application realm name this way: <login-config> <auth-method>DIGEST</auth-method> <realm-name>MyRealmName</realm-name> </login-config> Now, let's create a new security domain in JBoss, so we can manage the authentication mechanism DIGEST. In the file JBOSS_HOME/standalone/configuration/standalone.xml, on the section <security-domains>, let's add the following entry: <security-domain name="domainDigest" cache-type ="default"> <authentication> <login-module code="UsersRoles" flag="required"> <module-option name="usersProperties" value="${jboss.server.config.dir} /application-users.properties"/> <module-option name="rolesProperties" value="${jboss.server.config.dir}/ application-roles.properties"/> <module-option name="hashAlgorithm" value="MD5"/> <module-option name= "hashEncoding" value="RFC2617"/> <module-option name="hashUserPassword" value="false"/> <module-option name="hashStorePassword" value="true"/> <module-option name="passwordIsA1Hash" value="true"/> <module-option name="storeDigestCallback" value=" org.jboss.security.auth.callback.RFC2617Digest"/> </login-module> </authentication> </security-domain> Finally, in the application, change the security domain name in the file jboss-web.xml as shown in the following snippet: <?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>java:/jaas/domainDigest</security-domain> </jboss-web> We are going to change the authentication method from BASIC to DIGEST in the web.xml file. Also we enter the name of the security realm; all these changes must be applied in the tag login-config, this way: <login-config> <auth-method>DIGEST</auth-method> <realm-name>MyRealmName</realm-name </login-config> Now, restart the application server and then redeploy the application on JBoss. To do this, execute the next command on the terminal: mvn jboss-as:redeploy Authentication through certificates It is a mechanism in which a trust agreement is established between the server and the client through certificates. They must be signed by an agency established to ensure that the certificate presented for authentication is legitimate, it is known as CA. This security mechanism needs that our application server uses HTTPS as communication protocol. So we must enable HTTPS. Let's add a connector in the standalone.xml file; look for the following line: <connector name="http" Add the following block of code: <connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true"> <ssl password="changeit" certificate-key-file="${jboss.server.config.dir}/server.keystore" verify-client="want" ca-certificate-file="${jboss.server.config.dir}/server.truststore"/> </connector> Next we add the security domain: <security-domain name="RequireCertificateDomain"> <authentication> <login-module code="CertificateRoles" flag="required"> <module-option name="securityDomain" value="RequireCertificateDomain"/> <module-option name="verifier" value=" org.jboss.security.auth.certs.AnyCertVerifier"/> <module-option name="usersProperties" value= "${jboss.server.config.dir}/my-users.properties"/> <module-option name="rolesProperties" value= "${jboss.server.config.dir}/my-roles.properties"/> </login-module> </authentication> <jsse keystore-password="changeit" keystore-url= "file:${jboss.server.config.dir}/server.keystore" truststore-password="changeit" truststore-url ="file:${jboss.server.config.dir}/server.truststore"/> </security-domain> As you can see, we need two files: my-users.properties and my-roles.properties, both are empty and located in the JBOSS_HOME/standalone/configuration path. We are going to add the <user-data-constraint> tag in the web.xml in this way: <security-constraint> ...<user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> Then, change the authentication method to CLIENT-CERT: <login-config> <auth-method>CLIENT-CERT</auth-method> </login-config> And finally change the security domain in the jboss-web.xml file in the following way: <?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>RequireCertificateDomain</security-domain> </jboss-web> Now, restart the application server, and redeploy the application with Maven: mvn jboss-as:redeploy API keys With the advent of cloud computing, it is not difficult to think of applications that integrate with many others available in the cloud. Right now, it's easy to see how applications interact with Flickr, Facebook, Twitter, Tumblr, and so on through APIKeys usage. This authentication method is used primarily when we need to authenticate from another application but we do not want to access the private user data hosted in another application, on the contrary, if you want to access this information, you must use OAuth. Today it is very easy to get an API key. Simply log into one of the many cloud providers and obtain credentials, consisting of a KEY and a SECRET, the same that are needed to interact with the authenticating service providers. Keep in mind that when creating an API Key, accept the terms of the supplier, which clearly states what we can and cannot do, protecting against abusive users trying to affect their services. The following chart shows how this authentication mechanism works: Summary In this article, we went through some models of authentication. We can apply them to any web service functionality we created. As you realize, it is important to choose the correct security management, otherwise information is exposed and can easily be intercepted and used by third parties. Therefore, tread carefully. Resources for Article: Further resources on this subject: RESTful Java Web Services Design [Article] Debugging REST Web Services [Article] RESTful Services JAX-RS 2.0 [Article]
Read more
  • 0
  • 0
  • 3403

article-image-excel-2010-financials-adding-animations-excel-graphs
Packt
28 Jun 2011
3 min read
Save for later

Excel 2010 Financials: Adding Animations to Excel Graphs

Packt
28 Jun 2011
3 min read
  Excel 2010 Financials Cookbook Powerful techniques for financial organization, analysis, and presentation in Microsoft Excel      Getting ready We will start this recipe with a single column graph demonstrating profitability. The dataset for this graph is cell A1. Cell A1 has the formula =A2/100. Cell A2 contains the number 1000: How to do it... Press Alt + F11 on the keyboard to open the Excel Visual Basic Editor (VBE). Once in the VBE, choose Insert | Module from the file menu. Enter the following code: Sub Animate() Dim x As Integer x = 0 Range("A2").Value = x While x < 1000 x = x + 1 Range("A2").Value = Range("A2").Value + 1 For y = 1 To 500000 Next DoEvents Wend End Sub The code should be formatted within the VBE code window as follows: Save your work and close the VBE. Once back at the worksheet, from the Ribbon, choose View | Macros | View Macros. Select the Animate macro and choose Run. The graph for profitability will now drop to 0 and slowly rise to account for the full profitability. How it works... The graph was set to use the data within cell A1 as the dataset to graph. While there was a value within the cell, the graph shows the column and corresponding value. If you were to manually change the value of cell A1 and press enter, the graph would also change to the new value. It is this update event that we harness within the VBA macro that was added. Sub Animate() Dim x As Integer x = 0 Here we first declare and set any variables that we will need. The value of x will hold the overall profit: Range("A2").Value = x While x < 1000 x = x + 1 Range("A2").Value = Range("A2").Value + 1 For y = 1 To 500000 Next DoEvents Wend Next, we choose cell A2 from the worksheet and set its value to x (which begins as 0). Since cell A1 is set to be A2/100, A1 (which is the graph dataset) is now zero. Using a "while" clause in Excel, we take x and add 1 to its value, then pause a moment using DoEvents, to allow Excel to update the graph, then we repeat adding another value of 1. This is repeated until x is equal to 1000 which when divided by 100 as in the formula for A1, becomes 10. Now, the profitability we end with in our animation graph is 10. End Sub There's more... We can change the height of the profitability graph by simply changing the 1000 in the While x < 1000 line. By setting this number to 900, the graph will only grow to the profit level of nine. Further resources on this subject: Excel 2010 Financials: Using Graphs for Analysis [Article] Load Testing Using Visual Studio 2008 [Article] How to Manage Content in a List in Microsoft Sharepoint [Article] Sage ACT! 2011: Creating a Quick Report [Article] Tips and Tricks: Report Page in IBM Cognos 8 Report Studio [Article]
Read more
  • 0
  • 0
  • 3402

article-image-apache-ofbiz-service-engine-part-1
Packt
21 Oct 2009
6 min read
Save for later

Apache OFBiz Service Engine: Part 1

Packt
21 Oct 2009
6 min read
Defining a Service We first need to define a service. Our first service will be named learningFirstService. In the folder ${component:learning}, create a new folder called servicedef. In that folder, create a new file called services.xml and enter into it this: <?xml version="1.0" encoding="UTF-8" ?> <services xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/services.xsd"> <description>Learning Component Services</description> <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> <description>Our First Service</description> <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> </service> </services> In the file ${component:learning}ofbiz-component.xml, add after the last <entity-resource> element this: <service-resource type="model" loader="main" location="service def/services.xml"/> That tells our component learning to look for service definitions in the file ${component:learning}servicedefservices.xml. It is important to note that all service definitions are loaded at startup; therefore any changes to any of the service definition files will require a restart! Creating the Java Code for the Service In the package org.ofbiz.learning.learning, create a new class called LearningServices with one static method learningFirstService: package org.ofbiz.learning.learning; import java.util.Map; import org.ofbiz.service.DispatchContext; import org.ofbiz.service.ServiceUtil; public class LearningServices { public static final String module = LearningServices.class.getName(); public static Map learningFirstService(DispatchContext dctx, Map context){ Map resultMap = ServiceUtil.returnSuccess("You have called on service 'learningFirstService' successfully!"); return resultMap; } } Services must return a map. This map must contain at least one entry. This entry must have the key responseMessage (see org.ofbiz.service.ModelService.RESPONSE_MESSAGE), having a value of one of the following: success or ModelService.RESPOND_SUCCESS error or ModelService.RESPOND_ERROR fail or ModelService.RESPOND_FAIL By using ServiceUtil.returnSuccess() to construct the minimal return map, we do not need to bother adding the responseMessage key and value pair. Another entry that is often used is that with the key successMessage (ModelService.SUCCESS_MESSAGE). By doing ServiceUtil.returnSuccess("Some message"), we will get a return map with entry successMessage of value "Some message". Again, ServiceUtil insulates us from having to learn the convention in key names. Testing Our First Service Stop OFBiz, recompile our learning component and restart OFBiz so that the modified ofbiz-component.xml and the new services.xml can be loaded. In ${component:learning}widgetlearningLearningScreens.xml, insert a new Screen Widget: <screen name="TestFirstService"> <section> <widgets> <section> <condition><if-empty field-name="formTarget"/></condition> <actions> <set field="formTarget" value="TestFirstService"/> <set field="title" value="Testing Our First Service"/> </actions> <widgets/> </section> <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}"> <decorator-section name="body"> <include-form name="TestingServices" location="component://learning/widget/learning/LearningForms.xml"/> <label text="Full Name: ${parameters.fullName}"/> </decorator-section> </decorator-screen> </widgets> </section> </screen> In the file ${component:learning}widgetlearningLearningForms.xml, insert a new Form Widget: <form name="TestingServices" type="single" target="${formTarget}"> <field name="firstName"><text/></field> <field name="lastName"><text/></field> <field name="planetId"><text/></field> <field name="submit"><submit/></field> </form> Notice how the formTarget field is being set in the screen and used in the form. For now don't worry about the Full Name label we are setting from the screen. Our service will eventually set that. In the file ${webapp:learning}WEB-INFcontroller.xml, insert a new request map: <request-map uri="TestFirstService"> <event type="service" invoke="learningFirstService"/> <response name="success" type="view" value="TestFirstService"/> </request-map> The control servlet currently has no way of knowing how to handle an event of type service, so in controller.xml we must add a new handler element immediately under the other <handler> elements: <handler name="service" type="request" class="org.ofbiz.webapp.event.ServiceEventHandler"/> <handler name="service-multi" type="request" class="org.ofbiz.webapp.event.ServiceMultiEventHandler"/> We will cover service-multi services later. Finally add a new view map: <view-map name="TestFirstService" type="screen" page="component://learning/widget/learning/LearningScreens.xml#TestFirstService"/> Fire to webapp learning an http OFBiz request TestFirstService, and see that we have successfully invoked our first service: Service Parameters Just like Java methods, OFBiz services can have input and output parameters and just like Java methods, the parameter types must be declared. Input Parameters (IN) Our first service is defined with two parameters: <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> Any parameters sent to the service by the end-user as form parameters, but not in the services list of declared input parameters, will be dropped. Other parameters are converted to a Map by the framework and passed into our static method as the second parameter. Add a new method handleInputParamaters to our LearningServices class. public static Map handleParameters(DispatchContext dctx, Map context){ String firstName = (String)context.get("firstName"); String lastName = (String)context.get("lastName"); String planetId= (String)context.get("planetId"); String message = "firstName: " + firstName + "<br/>"; message = message + "lastName: " + lastName + "<br/>"; message = message + "planetId: " + planetId; Map resultMap = ServiceUtil.returnSuccess(message); return resultMap; } We can now make our service definition invoke this method instead of the learningFirstService method by opening our services.xml file and replacing: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> with: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="handleParameters"> Once again shutdown, recompile, and restart OFBiz. Enter for fields First Name, Last Name, and Planet Id values Some, Name, and Earth, respectively. Submit and notice that only the first two parameters went through to the service. Parameter planetId was dropped silently as it was not declared in the service definition. Modify the service learningFirstService in the file ${component:learning}servicedefservices.xml, and add below the second parameter a third one like this: <attribute name="planetId" type="String" mode="IN" optional="true"/> Restart OFBiz and submit the same values for the three form fields, and see all three parameters go through to the service.  
Read more
  • 0
  • 0
  • 3399
article-image-layout-dojo-part-2
Packt
15 Oct 2009
12 min read
Save for later

Layout in Dojo: Part 2

Packt
15 Oct 2009
12 min read
GridContainer There are a lot of sites available that let you add a lot of rss feeds and assorted widgets to a personal page, and which then also let you arrange them by dragging the widgets themselves around the page. One of the most known examples is iGoogle, Google's personal homepage for users with a staggering amount of widgets that are easy to move around. This functionality is called a GridContainer in Dojo. If you're not familiar with the concept and have never used a service which lets you rearrange widgets, it works like this: The GridContainer defines a number of different columns, called zones. Each column can contain any number of child widgets, including other containers (like AccordionContainer or BorderContainer). Each child widget becomes draggable and can be dragged into a new position within its own column, or dragged to a new position in another column. As the widget gets dragged, it uses a semi-transparent 'avatar'. As the widget gets dragged, possible target drop zones open up and close themselves dynamically under the cursor, until the widget is dropped on one of them. When a widget is dropped, the target column automatically rearranges itself to make the new widget fit. Here is an example from test_GridContainer.html in /dojox/layout/tests/. This is what the GridContainer looks like from the beginning: It has three columns (zones) defined which contain a number of child widgets. One of them is a Calendar widget, which is then dragged to the second column from its original position in the third: Note the new target area being offered by the second column. This will be closed again if we continue to move the cursor over to the first column. Also, in the example above, transparency of 1.0 (none) is added to the avatar, which looks normal. Finally, the widget is dropped onto the second column, both the source and target column arrange their widgets according to whether one has been added or removed. The implications of this is that it becomes very simple to create highly dynamical interfaces. Some examples might be: An internal "dashboard" for management or other groups in the company which needs rearrangeable views on different data sources. Portlets done right. Using dojox.charting to create different diagrammatic views on data sources read from the server, letting the user create new diagrams and rearranging them in patterns or groups meaningful to the current viewer. A simple front-end for a CMS-system, where the editor widget is used to enter text, and the user can add, delete or change paragraphs as well as dragging them around and rearranging their order. An example of how to create a GridContainer using markup (abbreviated) is as follows: <div id="GC1" dojoType="dojox.layout.GridContainer" nbZones="3" opacity="0.7" allowAutoScroll="true" hasResizableColumns="false" withHandles="true" acceptTypes="dijit.layout.ContentPane, dijit.TitlePane, dijit.ColorPalette, dijit._Calendar"><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?1 !</div><div dojoType="dijit.TitlePane" title="Ergo">Non ergo erunt homines deliciis ...</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?2 !</div><div dojoType="dijit.layout.ContentPane" title="Intellectum">Intellectum est enim mihi quidem in multis, et maxime in me ipso, sed paulo ante in omnibus, cum M....</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?3 !</div><div dojoType="dijit.layout.ContentPane" class="cpane" label="Content Pane">Content Pane n?4 !</div><div dojoType="dijit._Calendar"></div></div> The GridContainer wraps all of its contents.These are not added is not added in a hierarchical manner, but instead all widgets are declared inside the GridContainer element. When the first column's height is filled, the next widget in the list gets added to the next column, and so on. This is a quite unusual method of layout, and we might see some changes to this mode of layout since the GridContainer is very much beta [2008]. The properties for the GridContainer are the following: //i18n: Object//Contain i18n ressources.i18n: null,//isAutoOrganized: Boolean://Define auto organisation of children into the grid container.isAutoOrganized : true,//isRightFixed: Boolean//Define if the right border has a fixed size.isRightFixed:false,//isLeftFixed: Boolean//Define if the left border has a fixed size.isLeftFixed:false,//hasResizableColumns: Boolean//Allow or not resizing of columns by a grip handle.hasResizableColumns:true,//nbZones: Integer//The number of dropped zones.nbZones:1,//opacity: Integer//Define the opacity of the DnD Avatar.opacity:1,//minColWidth: Integer//Minimum column width in percentage.minColWidth: 20,//minChildWidth: Integer//Minimun children with in pixel (only used for IE6 that doesn't//handle min-width css propertyminChildWidth : 150,//acceptTypes: Array//The gridcontainer will only accept the children that fit to//the types.//In order to do that, the child must have a widgetType or a//dndType attribute corresponding to the accepted type.acceptTypes: [],//mode: String//location to add columns, must be set to left or right(default)mode: "right",//allowAutoScroll: Boolean//auto-scrolling enable inside the GridContainerallowAutoScroll: false,//timeDisplayPopup: Integer//display time of popup in milisecondstimeDisplayPopup: 1500,//isOffset: Boolean//if true : Let the mouse to its original location when moving//(allow to specify it proper offset)//if false : Current behavior, mouse in the upper left corner of//the widgetisOffset: false,//offsetDrag: Object//Allow to specify its own offset (x and y) onl when Parameter//isOffset is trueoffsetDrag : {}, ////withHandles: Boolean//Specify if there is a specific drag handle on widgetswithHandles: false,//handleClasses: Array//Array of classes of nodes that will act as drag handleshandleClasses : [], The property isAutoOrganized, which is set to true by default, can be set to false, which will leave holes in your source columns, and require you to manage the space in the target columns yourself. The opacity variable is the opacity for the 'avatar' of the dragged widget, where 1 is completely solid, and 0 is completely transparent. The hasResizableColumns variable also adds SplitContainer/BorderContainer splitters between columns, so that the user can change the size ratio between columns. The minColWidt/minChildWidth variables manage the minimum widths of columns and child widgets in relation to resizing events. The AcceptTypes variable is an important property, which lets you define which classes you allow to be dropped on a column. In the above example code, that string is set to dijit.layout.ContentPane, dijit.TitlePane, dijit.ColorPalette, dijit._Calendar. This makes it impossible to drop an AccordionContainer on a column. The reason for this is that certain things would want to be fixed, like status bars or menus, but still inside one of the columns. The withHandles variable can be set to true if you want each widget to get a visible 'drag handle' appended to it. RadioGroup The source code of dojox.layout.RadioGroup admits that it probably is poorly named, because it has little to do with radio buttons or groups of them, per se, even if this was probably the case when it was conceived. The RadioGroup extends the StackContainer, doing something you probably had ideas about the first time you saw it – adding flashy animations when changing which child container is shown. One example of how to use StackContainer and its derivatives is an information box for a list of friends. Each information box is created as a ContentPane which loads its content from a URL. As the user clicks on or hovers over the next friend on a nearby list, an event is triggered to show the next item (ContentPane) in the stack. Enter the RadioGroup, which defines its own set of buttons that mirror the ContentPanes which it wraps. The unit test dojox/layout/tests/test_RadioGroup.html defines a small RadioGroup in the following way: <div dojoType="dojox.layout.RadioGroup" style="width:300px; height:300px; float:left;" hasButtons="true"><div dojoType="dijit.layout.ContentPane" title="Dojo" class="dojoPane" style="width:300px; height:300px; "></div><div dojoType="dijit.layout.ContentPane" title="Dijit" class="dijitPane" style="width:300px; height:300px; "></div><div dojoType="dijit.layout.ContentPane" title="Dojox" class="dojoxPane" style="width:300px; height:300px; "></div></div> As you can see, it does not take much space. In the test, the ContentPanes are filled with only the logos for the different parts of Dojo, defined as background images by CSS classes. The RadioGroup iterates over each child ContentPane, and creates a "hover button" for it, which is connected to an event handler which manages the transition, so if you don' t have any specific styling for your page and just want to get a quick mock-up done, the RadioGroup is very easy to work with. The default RadioGroup works very much like its parent class, StackContainer, mostly providing a simple wrapper that generates mouseover buttons. In the same file that defines the basic RadioGroup, there are two more widgets: RadioGroupFade and RadioGroupSlide. These have exactly the same kind of markup as their parent class, RadioGroup. RadioGroupFade looks like this in its entirety: dojo.declare("dojox.layout.RadioGroupFade", dojox.layout.RadioGroup, { // summary: An extension on a stock RadioGroup, that fades the //panes. _hideChild: function(page){ // summary: hide the specified child widget dojo.fadeOut({ node:page.domNode, duration:this.duration, onEnd: dojo.hitch(this,"inherited", arguments) }).play(); }, _showChild: function(page){ // summary: show the specified child widget this.inherited(arguments); dojo.style(page.domNode,"opacity",0); dojo.fadeIn({ node:page.domNode, duration:this.duration }).play(); }}); As you can see, all it does is override two functions from RadioGroup which manage how to show and hide child nodes upon transitions. The basic idea is to use the integral Dojo animations fadeIn and fadeOut for the effects. The other class, RadioGroupSlide, is a little bit longer, but not by much. It goes beyond basic animations and uses a specific easing function. In the beginning of its definition is this variable: // easing: Function// A hook to override the default easing of the pane slides.easing: "dojo.fx.easing.backOut", Later on, in the overridden _hide and _showChild functions, this variable is used when creating a standalone animation: ...this._anim = dojo.animateProperty({ node:page.domNode, properties: { left: 0, top: 0 }, duration: this.duration, easing: this.easing, onEnd: dojo.hitch(page,function(){ if(this.onShow){ this.onShow(); } if(this._loadCheck){ this._loadCheck(); } })});this._anim.play();   What this means is that it is very simple to change (once again) what kind of animation is used when hiding the current child and showing next, which can be very usable. Also, you can see that it is very simple to create your own subclass widget out of RadioGroup which can use custom actions when child nodes are changed. ResizeHandle The ResizeHandle tucks a resize handle, as the name implies, into the corner of an existing element or widget. The element which defines the resize handle itself need not be a child element or even adjacent to the element which is to receive the handle. Instead the id of the target element is defined as an argument to the ResizeHandle as shown here: <div dojoType="dijit.layout.ContentPane" title="Test window" style="width: 300px; height: 200px; padding:10px; border: 1px solid #dedede; position: relative; background: white;" id="testWindow"> ...<div id="hand1" dojoType="dojox.layout.ResizeHandle" targetId="testWindow"></div> </div> In this example, a simple ContentPane is defined first, with some custom styling to make it stand out a little bit. Further on in the same pages comes a ResizeHandle definition which sets the targetId property of the newly created ResizeHandle to that of the ContentPane ('testWindow'). The definition of the ResizeHandle class shows some predictable goodies along with one or two surprises: //targetContainer: DomNode//over-ride targetId and attch this handle directly to a//reference of a DomNodetargetContainer: null,//resizeAxis: String//one of: x|y|xy limit resizing to a single axis, default to xy ...resizeAxis: "xy",//activeResize: Boolean//if true, node will size realtime with mouse movement,//if false, node will create virtual node, and only resize target//on mouseUp.activeResize: false,//activeResizeClass: String//css class applied to virtual resize node.activeResizeClass: 'dojoxResizeHandleClone',//animateSizing: Boolean//only applicable if activeResize = false. onMouseup, animate the//node to the new size.animateSizing: true,//animateMethod: String//one of "chain" or "combine" ... visual effect only.combine will "scale"//node to size, "chain" will alter width, then heightanimateMethod: 'chain',//animateDuration: Integer//time in MS to run sizing animation. if animateMethod="chain",//total animation playtime is 2*animateDuration.animateDuration: 225,//minHeight: Integer//smallest height in px resized node can beminHeight: 100,//minWidth: Integer//smallest width in px resize node can beminWidth: 100, As could be expected, it is simple to change if the resizing is animated during mouse move or afterwards (activeResize: true/false). If afterwards, the animateDuration declares in milliseconds the length of the animation. A very useful property is the ability to lock the resizing action to just one of the two axes. The resizeAxis property defaults to xy, but can be set to only x or only y as well. Both restricts resizing to only one axis and also changes the resize cursor to show correct feedback to which axis is 'active' at the moment. If you at any point want to remove the handle, calling destroy() on it will remove it from the target node without any repercussions.
Read more
  • 0
  • 0
  • 3398

article-image-titanium-best-practices
Packt
15 Mar 2013
13 min read
Save for later

Titanium Best Practices

Packt
15 Mar 2013
13 min read
(For more resources related to this topic, see here.) CommonJS CommonJS is a set of specifications, and its purpose is to give a common guide to building JavaScript frameworks. It is not a framework in its own right. Appcelerator implementing these standards to their Titanium framework brings it inline with other frameworks such as NodeJS, and enables us as developers to use the same practices in more than one framework. The implications of this cannot be overstated. Developers can now switch between JavaScript frameworks, which have implemented the CommonJS model, without having a massive learning curve on the framework itself. CommonJS works by using an initial bootstrap file, which in Titanium is app.js. You then abstract your code into separate modules that are required into other modules when needed. Within Titanium, you can have native modules that enhance and expand the Titanium framework. These should not be confused with a CommonJS module, which is part of the main application. Code formatting How often have you needed to modify code that was written by other people or has been updated, modified, rewritten, or just generally messed around with? You find different people using different coding styles, braces on different lines, and equals signs at different positions; the list is endless. You then have to work your way through this code, getting more and more annoyed. Titanium Studio has a solution—an automatic code formatter, which you can set up as you require. To get to the configuration settings, go through the main menu to Preferences | Titanium Studio | Formatter, select JavaScript , and click on the edit icon. You will see the Preferences panel and you can configure it as required. If you wish to have these configurations across your development team, then you can export and import them as required. To format a file's code, open the file, go to the main menu, and select Source | Format. Alternatively, if you are on a Mac, the relevant shortcut keys are shift +command +F. If you have selected a section of code then that will be formatted, otherwise the whole file will be formatted. A gotcha with the formatter: If there are too many JavaScript errors it won't format the code. Code validation As developers, we spend our days hunting down spurious code anomalies. It could be a missing comma, semicolon, or that an event listener wasn't added while looping an array of objects. Anything that can make this task easier and show potential issues while we are writing code is a good thing. JSLint is one of those tools that you could use, as it highlights potential issues as you code. It has been described as your worst nightmare but also your best friend. When you first start using it, it may drive you mad with some of the seemingly meaningless warnings, but sort them out and be persistent; it will improve your codebase in the long term. Titanium Studio has JSLint built in but switched off by default. To enable it, go to Preferences | Titanium Studio | Validation, select JavaScript , and switch on JSLint Validator. As you can see, there are other validators on the list, which also help give you a hit list of potential issues. It is worth spending a little time making sure you understand what these are and how they work. Comment meaningfully Adding comments to your code should not be seen as a chore, instead they can be as important as the code itself. A well-commented codebase can and will save hours in the future, as you or a colleague go to update and maintain it. Always put a comment block at the start of source files, explain what the file does, and include a maintenance log, where the date, time, developer's name, and a brief description of the changes can be maintained. If you have a complex function put a comment block before it, explaining what it does. Also place inline comments where needed to explain certain pieces of code. /* * A CommonJS Module. * * This module does something … * * Author : Name * * Date : Today * * Maintenance Log * * Date : Author: * Changes : * */ Do not add comments for the sake of adding them. Make them meaningful, relevant, and useful. Too many comments can confuse the code structure. Do not pollute the global object Within an application you can define various application objects. Declare and use these with caution, as they use up resources and can easily cause clashes with other private and local objects. Application-level variables are not really required and should be avoided. If you require a small piece of data to move around the application, consider using persistent data or passing it to the required modules. Application-level event handlers are required for various tasks including, amongst others, background services and geolocation. If you do use them, always remove them when they are no longer needed. To control the flow of an application, you may need to set up a global listener, but you only need one with a common function to control the flow. In CommonJS there is no global scope; declaring a variable within a module makes it private to that module. Declaring variables in app.js as Ti.App.varName = [], does make them global, but is highly discouraged. JavaScript instance A JavaScript instance is where a session of the interpreter is invoked. In Titanium it is possible to create multiple instances within a single application. This is done by creating a window object with a url property to load the content. Var win = Ti.UI.createwindow({ url: '/app/ui/newWindow.js' }); Don't do this unless you have a very, very specific requirement. To benefit from all the advantages CommonJS provides, always work in a single JavaScript instance. The consequences of multiple instances include no scope across them, additional memory and resource usage, and a high risk of memory leaks. CommonJS modules With the adoption of the CommonJS specification by Appcelerator into the Titanium framework, you should only use the CommonJS modules, which are also referred to as factories. This provides many advantages: separation of code into specific modules, a more structured codebase, separate object scope, code maintainability, and much more. By using this method it becomes very difficult to pollute the global scope, as each module has its own object scope. Understanding this is key to the CommonJS method. Each module or factory contains functions and variables that can be exported; unless they are exported they are private to that module. This enables variable or function names to be the same in different modules without a scoping clash. By exporting only what is required at the end of the module, it enables the module to be self contained. /* A typical module format myModule.js */ var object1 = "1234"; var object2 = "5678"; /* My modules function */ functionmyModule(args){ … do something nice return mainObject; } exports.object1 = object1; exports.myModule = myModule; When a CommonJS module is required by another module it is loaded into memory. If you then require the same module elsewhere, it doesn't reload it into memory; it just makes it available to the new calling module. This means t hat if the first requiring module sets a value in the called module, when the called module is required by another module, the values which have been set are still set. It doesn't load a new instance of the module and reinitialize all the values. A few rules about modules: Only load them when needed Only export what is required by the calling module Use prototype where appropriate Avoid recursive requires Working with CommonJS recursive requires can cause major issues and, basically, you can't do it. A recursive require is where module A requires module B and module B then requires module A. You will quickly notice if you try this that this leads to a loop trying to process the continual call of the requires, and finally dies with a nondescript error message. CommonJS best practices CommonJS is one of the best things to have happened to the Titanium framework. To get the most out of the framework and the enhanced performance, these are a few things that should be considered: Be modular Be private Return an object Protect the global scope Control file loading One of the main advantages of CommonJS is the way it lends itself to creating well-structured, separated code. By being modular you create specific modules for separate sections of the code, i.e. a separate module for each window. This methodology facilitates the creation of common modules enabling a constructive codebase that is easy to understand and maintain. A good example of a common module would be one that contains the geolocation code and is then used across the whole application. Common modules enable the code to be extracted down, but don't go too far. It is tempting to extract code out into its own module when it actually lives in the module it is in. Do not be tempted to take code modularization to the extreme, having a module for each function is not necessary or productive. Remember that modules are loaded into memory once they have been required and they remain there. Making functions and variables private to a module maintains the module's integrity. Do not export all the functions in a module unless they are actually called from the requiring module. Export the required functions and variables at the end of the module, not by default. The following code example shows the two methods for exporting functions: // This exports the function inline exports.outFunc = function () { .. code .. return object; } // This only exports the function when and if required. function outFunc() { .. code .. return object; } exports.outFunc = outFunc; By defining the module functions in the second method, they become local to that module. This means that they can be used directly by any other function within the module. As you separate your code into modules, separate your modules into functions. Having one exported parent function that returns the main object after processing through other functions is a good practice. It is quite easy to declare module variables; you just declare them outside of any function. This gives them a scope that is global to the module. It is a very good way of maintaining a persistent state across the calling modules, but use them sparingly as they use up more resources. JavaScript, by default, returns the last action of a function to the calling function. This may not always be what is required, especially in the CommonJS model. Always return what you require from a function even if that is nothing. // New window function returning the null object. functionnewWin() { // Do something return; } exports.newWin = newWin; For an exported function always return the function's main object. Hence, creating a new window in a function should return that window object as the following code example shows: // New window function returning the parent object. function newWin() { var win = Ti.UI.createWindow({ .. parameters .. }); return win; } exports.newWin = newWin; The global scope should be considered as nonexistent, but you can still add application-level variables. If you have to use these, only declare them in the app.js file; do not declare them in any of the modules. At times you will have to create an application event listener in a module. Only do this when you have to and always, always remove the listener after you have finished with it. The following code example shows an event listener added with an in-built function. This is not good practice, as you cannot remove it later. The only way it will be removed is when the parent object is destroyed, which for application-level listeners is when the application is stopped, not put into background. function adList() { varmainObj = Ti.UI.createImageView(); mainObj.addEventListener('click', function(e) { .. do something here .. }); return mainObj; } Instead of defining listeners with an in-built function, always declare them to a calling function as the following example shows. They can then easily be removed, as you have to declare the called function to be identical in both addEventListener and removeEventListener. varmainObj = null; function eveList(e){ .. do something here … mainObj.removeEventListener('click', eveList); } function adList() { mainObj = Ti.UI.createImageView(); mainObj.addEventListener('click', eveList); return mainObj; } Managing memory We have explored some of the practices that will help in managing the application's memory. These practices range from controlling when the modules file is loaded to not using application-level events or variables. When you open a window, it is added to the window stack, and every time you open that window it is added to the stack. If you have a navigation system that enables you to move through the windows in any order, it is likely that you will end up with a large stack. Close the windows when they are not in use. varwin =i.UI.createWindow(); varwinBut =i.UI.createButton({ title : 'Press' }); function loadWin2() { varwin = Ti.UI.createWindow(); win.close(); win = null; win2.open(); } winBut.addEventListener('click', loadWin2); // opening a window win.add(winBut); win.open(); Some additional memory-intensive APIs in Titanium are web views, large tables, and events. It is not a good idea to have more than one web view instance running in the application at a time. If you do not close the window containing the web view instance and move to another one, at least remove the web view instance from the previous window and reload it when focus is made. The same applies to tables and map views. When you remove an object such as a web view from a window it may not always release the memory—even closing a window does not always release the memory. In all cases, null is your friend. The final code example shows a window with web view, an event listener, and how to clean up when a window is closed: // clean up example module function createWin() { var win = Ti.UI.createWindow(); varwebV = Ti.UI.createWebView(); win.addEventListener('open', openFunc); win.addEventListener('close', function(e) { win.removeEventListener('open'openFunc); win.remove(webV); webV = null; win = null; } win.add(webV); return win; } In this example the close event doesn't call another function. This is acceptable because when we close the window, the close event will fire, which nulls the win object and this removes the object's event listener. It is done this way to prevent having to use module variables to handle the window and web view objects being cleaned up in another function. Summary As you have seen, there are quite a few considerations to take into account when coding with Titanium. Some of these can also be applied to other programming languages. It is completely optional to follow best practices; they are there as a guide, as a place to start, and as a way to manage your code going forward. As a developer you will find your own way to implement the methodology used within the application, you will decide when, where, and what comments to add, which code format to use, and which module to put what code into. But best practices and guidelines are developed for a reason; they keep code consistent within the application, they allow other developers to pick up what is going on quickly, and enable clean and reliable code. Always apply a good coding style to your application. You will thank yourself in the future. Resources for Article : Further resources on this subject: Animating Properties and Tweening Pages in Android 3-0 [Article] Creating, Compiling, and Deploying Native Projects from the Android NDK [Article] Appcelerator Titanium: Creating Animations, Transformations, and Understanding Drag-and-drop [Article]
Read more
  • 0
  • 0
  • 3396
Modal Close icon
Modal Close icon