Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
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

7018 Articles
article-image-model-design-accelerator
Packt
30 Jul 2013
6 min read
Save for later

Model Design Accelerator

Packt
30 Jul 2013
6 min read
(For more resources related to this topic, see here.) By the end of this article you will be able to use Model Design Accelerator to design a new Framework model. To introduce Model Design Accelerator, we will use a fairly simple schema based on a rental star schema, derived from the MySQL Sakila sample database.This database can be downloaded from http://dev.mysql.com/doc/sakila/en/. It is just one example of a number of possible dimensional models based on this sample database. The Model Design Accelerator user interface The user interface of Model Design Accelerator is very simple, consisting of only two panels: Explorer Tree: This contains details of the database tables and views from the data source. Model Accelerator: This contains a single fact table surrounded by four dimension tables, and is the main work area for the model being designed. By clicking on the labels (Explorer Tree and Model Accelerator) at the top of the window, it is possible to hide either of these panels, but having both these panels always visible is beneficial. Starting Model Design Accelerator Model Design Accelerator is started from the Framework Manager initial screen: Select Create a new project using Model Design Accelerator…. This will start the new project creation wizard, which is exactly the same as if you were starting any new project. Select the data source to import the database tables into the new model. After importing the database tables, the project creation wizard will display the Model Design Accelerator Introduction screen: After reading the instructions, click on the Close button to continue. This will then show the Model Design Accelerator workspace. Adding tables to your workspace The first step in creating your model with Model Design Accelerator is to add the dimension and fact tables to your model: From the Explorer panel,drag-and-drop dim_date ,dim_film ,dim_ customer, and dim_store to the four New Query Subject boxes in the Model Accelerator panel. After adding your queries, right-click on the boxes to rename the queries to Rental Date Dim,Film Dim ,Customer Dim, and Store Dim respectively. If not all query columns are required, it is also possible to expand the dimension tables and drag-and-drop individual columns to the query boxes. In the Explorer Tree panel,expand the fact_rental table by clicking on the (+) sign besides the name, and from the expanded tree drag-and-drop count_returns,count_rentals, and rental_duration columns to the Fact Query Subject box. Rename the Fact Query Subject to Rental Fact. Additional dimension queries can be added to the model by clicking on the top-left icon in the Model Accelerator panel, and then by dragging and dropping the required query onto the workplace window. Since we have a start_date and an end_date for the rental period, add a second copy of the date_dim table, by clicking on the icon and dragging the table from the Explorer view into the workspace. Also rename this query as Return Date Dim: Adding joins to your workspace After we have added our database table columns to the workspace, we now need to add the relationship joins between the dimension and fact tables. To do this: Double-click on the Rental Date Dim table, and this will expand the date_ dim and the fact_rental tables in the workspace window: Click on the Enter relationship creation mode link. Select the date_key column in the dim_date table, and the rental_date_ key column in the fact_rental table as follows: Click on the Create relationship icon: Click on OK to create this join. Close the Query Subject Diagram by clicking on the (X) symbol in the top-right corner. Repeat this procedure for each of the other four tables. The final model will look like the following screenshot: Generating Framework Manager model Once we have completed our model in Model Design Accelerator, we need to create a Framework Manager model: Click on the Generate Model button. Click on Yes to generate your model.The Framework Manager model will be generated and will open as follows:   When you generate your model, all of the Model Advisor tests are automatically applied to the resulting model. You should review any issues that have been identified in the Verify Results tab, and decide whether you need to fix them. When you generate the model only those query items required will be used to create the Framework Manager model. The Physical View tab will contain only those tables required by your star schema model. The Business View tab will contain model query subjects containing only the columns used in your star schema model. The Presentation View tab will only contain shortcuts to the query subjects that exist in the Business View tab. After generating your model, you can use Framework Manager to improve the model by adding calculations, filters, dimensions, measures, and so on. Each time you generate a Framework Manager model from your Model Design Accelerator model, a new namespace is created in the current Framework Manager model and any improvements you want to use will also need to be applied to these new namespaces. From Framework Manager you can return to Model Design Accelerator at any time to continue making changes to your star schema. To return to the Model Design Accelerator from within Framework Manager: From the Tools menu, select Run Model Design Accelerator. You may choose to continue with the same model or create a new model. To make your star schema model available to the report authors, you must first create a package and then publish the package to your Cognos Reporting Server. Summary In this article, we have looked at Model Design Accelerator. This is a tool that allows a novice modeler, or even an experienced modeler, to create a new Framework Manger model quickly and easily. Resources for Article: Further resources on this subject: Integrating IBM Cognos TM1 with IBM Cognos 8 BI [Article] How to Set Up IBM Lotus Domino Server [Article] IBM Cognos 10 BI dashboarding components [Article]
Read more
  • 0
  • 0
  • 1830

Packt
30 Jul 2013
8 min read
Save for later

Quick start – media files and XBMC

Packt
30 Jul 2013
8 min read
(For more resources related to this topic, see here.) Step 1 – naming or tagging media correctly Before you dive into adding your movies, television shows, and music, it's important to have properly formatted media. XBMC can automatically download (scrape) information about movies, television shows, and music videos, but it needs to have a consistent way of figuring out what the name of the movie or TV show is. Movies and television shows need to be named in a particular way and music needs to be tagged with a proper ID tag, in order for XBMC's scrapers to correctly identify each media. Naming movies Movies should be named with their name, followed by parenthesis containing the year when each movie was released. For example: \Movies\The Odessa File (1974).mp4 \Movies\The Day of the Jackal (1973).mp4 \Movies\Shrek (2001).mp4 Naming TV shows Television shows are normally kept in subfolders and each show is named with its name, the season, and the episode number. The format is Directory\Showname.s##.e##.file extension . For example: \TV\Futurama\Futurama.s03e01.mp4 \TV\Futurama\Futurama.s03e02.mp4 \TV\Futurama\Futurama.s03e03.mp4 Tagging music In order for XBMC to correctly scrape information about a song, the song needs a proper ID tag. ID tags are metadata about the song information, such as the artist, album title, song title, and song number. Programs like iTunes, Winamp, or EasyTAG (shown in the following screenshot) can be used to tag songs before they're uploaded/added to your XBMC library. Step 2 – getting the files to your XBMC computer If you've installed XBMC on a computer you use on a regular basis for ripping your music and video collection, you can skip to the Step 3 – adding files to your movie, TV show, or music library section. If you've installed XBMCbuntu to a separate computer, you need a way to get files from your desktop computer to your XBMCbuntu Media Center. Remember the computer name, username, and password you used during the XBMCbuntu installation? We're about to use that information. Because XBMCbuntu is based on Linux, there are several ways we can transfer files to our media server: NFS, Samba, SFTP, FTP, and a host of different services. For simplicity, we'll concentrate on SFTP and Samba. Name resolution You can see what IP address your XBMC media center is using by selecting System | System Info | Summary. Using your IP address you can send files to your XBMCbuntu via SFTP using a program like FileZilla or WS_FTP. But if you use DHCP, this gets a bit tedious when your IP address changes. Normally, you want to just use your XBMCbuntu computer name for SSH/ SFTP and file sharing activities. Setting up DNS is beyond the scope of this Instant guide, but there are a couple of things you can do to help with name resolution. Most routers have an option to assign a name to a system with a particular MAC address (which you can see on XBMC by navigating to System | System info and Network). In the following screenshot, I've added a static DHCP reservation for my XBMCbuntu machine called xbmc.  I found the MAC address by checking my router's Device list menu. If you're comfortable with the Linux command line, you can also obtain the MAC address of your network card by typing ifconfig (on Windows machines you can do the same at the command prompt by typing ipconfig). A router's menus and options vary depending on the router you use, but many have a section where you can assign DHCP reservations to a particular computer so it always gets the same address. You can make Windows computers see your XBMCbuntu system with one simple modification to your XBMC system. Edit the file /etc/nsswitch.conf and on the line that begins with hosts, add the word wins. Sending files via FileZilla FileZilla is a cross-platform, multiprotocol client for sending and receiving files from servers. Other clients exist, but FileZilla is licensed under the GPL license and available for Windows, Linux, and Mac OS X. Download FileZilla from https://filezilla-project.org/ , or if you're using a Debian-based flavor of Linux, just type in the following command in the console: sudo apt-get install filezilla Once FileZilla is installed, navigate to File | Site Manager (or just click on the Site Manager icon, the first icon). Enter the hostname you gave your XBMCbuntu machine in the Host section. Select SFTP SSH File Transfer Protocol| from the Protocol section. Select Normal from Login Type. In the User field enter the username you used when setting up XBMCbuntu. In thePassword field enter the password. Click on Connect. Once connected, local files default on the left-hand side of the screen and remote files on the right. Navigate to the files and folders you want on each side. To send a file, simply right-click the file and select Upload. You can upload multiple files using Ctrl and clicking on the filenames, and then right-clicking and selecting Upload. Configuring and sending files via Samba One of the reasons to use XBMCbuntu is that it sets up movies, music, TV shows, downloads, and system folders in your home directory and adds them to the Samba smb.conf configuration file. Samba is a suite of tools for interoperating with Windows systems. Samba is not a part of a normal Linux install, so if you're setting up XBMC manually under Linux, you'll need to install Samba, create a Samba password for your account, and set up each Samba share for movies, television shows, and music. This is one of the things that comes preconfigured on XBMCbuntu. XBMCbuntu saves you the steps of having to download Samba, create accounts, and configure shares. Linux understands Samba too; you can open a nautilus or nemo session, hold down Ctrl and press L, and type smb://yourservername/ to open a session. If you cannot see your XBMCbuntu Samba shares from your Windows system, make sure you've added WINS to the /etc/nsswitch.conf file; check to see that the NETBIOS name is the name you gave your XBMCbuntu system, and that the workgroups are the same on your Windows and XBMCbuntu machine. To send a file to the XBMCbuntu system from a Windows 7 machine, perform the following steps: Click on the Libraries icon in the taskbar. Under the Network section of the window that opens, click on the NETBIOS name of your XBMCbuntu server and choose the folder you want to copy to. Drag files from where you have them stored to the XBMCbuntu network folder you just opened. Depending on how much data you're copying, the process may take from a few seconds to several hours. Step 3 – adding files to your movie, TV show, or music library Once your music, movies and shows have been copied to your entertainment system, you need to tell XBMC what type of content you've added, and where to look for it.. XBMC's 10 foot interface makes adding content simple. For pictures and music, perform the following steps: Click on either Pictures or Music from the main menu, and then click on Add Source. In the Add Pictures / Music Source dialog box, click on Browse to browse to the directory where you've stored your pictures or music. (You'll notice blue and red icons; blue icons are local sources, red icons are network sources). Once you've found the directory you stored your media in, click on OK. Next give the source a name. You can add as many sources as you want, so it's a good idea to name them differently to stay organized. For television shows and movies, perform the following steps: Click on Videos from the main menu, click on Files from the submenu, and then click on Add Videos. In the Add Video Source dialog box, click on Browse to browse to the directory where you've stored your movies, television shows, or music videos, and then click onOK. Give the source a name. Again it's a good idea to give the source a name that reflects the content, movies on laptop share, for example. Next the Set content type dialog box appears showing three panels. Choose the type of video from the top-left dropdown. You can choose None, Music, Videos, TV shows, or Movies. As you choose the content type, the Choose a scraper panel on the right-hand side also changes. There is a default scraper for each video type, but you can also select Get more to get other scrapers for that type of content (sometimes desirable, if you're adding anime or content in another language). Select OK when you're done. XBMC now attempts to add the content to its video library. If the content is correctly named, XBMC will add it to the library. Summary This article covered the quick start of media files and XBMC in a very systematics and stepwise mode. The media files that we used here were the movie files, TV shows and music libraries. Resources for Article : Further resources on this subject: New iPad Features in iOS 6 [Article] Documentaries and Other Audio-Visual Projects with Celtx [Article] Getting Started with Audacity [Article]
Read more
  • 0
  • 0
  • 1413

article-image-sharepoint-2013-search
Packt
30 Jul 2013
11 min read
Save for later

SharePoint 2013 Search

Packt
30 Jul 2013
11 min read
(For more resources related to this topic, see here.) Features of SharePoint 2013 – Result types and design templates Both result types and design templates are new concepts introduced in SharePoint 2013. Kate Dramstad, a program manager from the SharePoint search team at Microsoft, describes both concepts in a single, easy-to-remember formula: result types + design templates = rich search experience . When we perform a search we get back results. Some results are documents, others are pictures, SharePoint items, or just about anything else. Up until SharePoint 2010, all results, no matter which type they were, looked quite the same. Take a look at the following screenshot showing a results page from FAST for SharePoint 2010: The results are dull looking, can't be told apart, and in order to find what you are looking for, you have to scan the results up and down with your eyes and zero in on your desired result. Now let's look at how results are displayed in SharePoint 2013: What a difference! The page looks much more alive and vibrant, with easy distinguishing of different result types and a whole new hover panel, which provides information about the hovered item and is completely customizable. Display templates Search, and its related web parts, makes heavy use of display templates instead of plain old XSLT ( Extensible Stylesheet Language Transformations ). Display templates are basically snippets of HTML and JavaScript, which control the appearance and behavior of search results. SharePoint ships with a bunch of display templates that we can use out of the box, but we can also create our own custom ones. Similar to master pages, it is recommended to copy an existing display template that is close in nature to what we strive to achieve and start our customization from it. Customizing a display template can be done on any HTML editor, or if you choose, even Notepad. Once we upload the HTML template, SharePoint takes care of creating the companion JavaScript file all by itself. If we tear apart the results page, we can distinguish four different layers of display templates: The layers are as follows: Filters layer : In the preceding screenshot they are highlighted with the green border on the left and numbered 1. This layer shows the new refinement panel area that is not limited to text alone, but also enables the use of UX elements such as sliders, sliders with graphs, and so on. Control layer : In the preceding screenshot they are highlighted with the red border in the middle and numbered 2. This layer shows that not only results but also controls can be templated. Item layer : In the preceding screenshot they are highlighted with the orange border in the middle and numbered 3. This layer shows that each result type can be templated to look unique. For example, in the screenshot we see how a site result (the first result), conversation results (next three results), and image result (last one) looks like. Each result type has its own display template. Hover panel layer : In the preceding screenshot, they are highlighted with the blue border on the right and numbered 4. They are introduced in SharePoint 2013, the hover panel shows information on a hovered result. The extra information can be a preview of the document (using Office Web Apps), a bigger version of an image or just about anything we like, as we can template the hover panel just like any other layer. Display templates are stored in a site's master page gallery under the Display templates folder. Each one of these layers is controlled by display templates. But if design templates are the beauty, what are the brains? Well, that is result types. Result types Result types are the glue between design templates (UX—user experience) and the type of search result they template. You can think of result types as the brain behind the templating engine. Using result types enables administrators to create display templates to be displayed based upon the type of content that is returned from the search engine. Each result type is defined by a rule and is bound to a result source. In addition, each result type is associated with a single display template. Just like display templates, SharePoint ships with it a set of out of the box result types that match popular content. For example, SharePoint renders Word document results using the Item_Word.html display templates within any result source if the item matches the Microsoft Word type of content. However, if an item matches the PDF type of content, the result will be rendered using the Item_PDF.html display template. Defining a result type is a process much like creating a query rule. We will create our first result type and display template towards the end of the article. Both result types and display templates are used not only for search results, but also for other web parts as well, such as the Content Search Web Part. Styling results in a Content Search Web Part The Content Search Web Part (CSWP) comes in handy when we wish to show search-driven content to users quickly and without any interaction on their side. When adding a CSWP we have two sections to set: Search Criteria and Display Templates . Each section has its unique settings, explained as follows: The search criteria section is equivalent to the result type. Using the Query Builder we tell the web part which result type it should get. The Query Builder enables us to either choose one of the built-in queries (latest documents, items related to current user, and so on) or build our own. In addition, we can set the scope of the search. It can either be the current site, current site collection, or a URL. For our example, we will set the query to be Documents(System) , meaning it searches for the latest documents, and the scope to Current site collection : Next, we set the display template for the control holding the results. This is equivalent to the Control layer we mentioned earlier. The CSWP provides three control templates: List , List with Paging , and Slideshow . The control templates change the way the container of the items looks. To compare the different templates, take a look at how the container looks when the List template is chosen: And the following screenshot displays how the exact same list looks when the Slideshow template is chosen: Since our content is not images, rendering the control as Slideshow makes no sense. Last but not least, we set the Item display template. As usual, SharePoint comes with a set of built-in item templates, each designated for different item types. By default, the Picture on left, 3 lines on right item display template is selected. By looking at the preceding screenshot we can see it's not right for our results. Since we are searching for documents, we don't have a picture representing them so the left area looks quite dull. If we change the Item display template to Two lines we will get a much more suitable result: Display templates allow us to change the look of our results instantly. While playing around with the out-of-the-box display templates is fun, extending them is even better. If you look at the Two lines template that we chose for the CSWP, it seems kind of empty. All we have is the document type, represented by an icon, and the name of the document. Let's extend this display template and add the last modified date and the author of the document to the display. Creating a custom display template As we mentioned earlier, the best way to extend a display template is to copy and paste a template that is close in nature to what we wish to achieve, and customize it. So, as we wish to extend the Two lines template, open SharePoint Designer, navigate to Master Page Gallery | Display Templates | Content Web Parts of the site you previously added the CSWP, and copy and paste the Item_TwoLines.html file into the same folder. Rename the newly created file to Item_TwoLinesWithExtraInfo.html. As soon as you save the new filename, refresh the folder. You'll notice that SharePoint automatically created a new file named Item_TwoLinesWithExtraInfo.js. The combination of the HTML and JavaScript file is what makes the magic of display templates come to life. Edit the Item_TwoLinesWithExtraInfo.html file, and change its title to Two Lines with Extra Info. Getting the new properties The first code block we should discuss is the CustomDocumentProperties block. Let's examine what it holds between its tags: <mso:CustomDocumentProperties> <mso:TemplateHidden msdt_dt="string">0</mso:TemplateHidden> <mso:ManagedPropertyMapping msdt_dt="string">'Link URL'{Link URL}:'Path','Line 1'…</mso:ManagedPropertyMapping> <mso:MasterPageDescription msdt_dt="string">This Item Display Template will show a small thumbnail…</mso:MasterPageDescription> <mso:ContentTypeId msdt_dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</ mso:ContentTypeId> <mso:TargetControlType msdt_dt="string">;#Content Web Parts;#</mso:TargetControlType> <mso:HtmlDesignAssociated msdt_dt="string">1</mso:HtmlDesignAssociated> <mso:HtmlDesignConversionSucceeded msdt_dt="string">True</mso:HtmlDesignConversionSucceeded> <mso:HtmlDesignStatusAndPreview msdt_dt="string">https://hippodevssp.sharepoint.com/search/_ catalogs/masterpage/Display%20Templates/Content%20Web%20Parts/Item_ TwoLinesWithExtraInfo.html, Conversion successful.</mso:HtmlDesignStatusAndPreview> </mso:CustomDocumentProperties> The most important properties from this block are: ManagedPropertyMapping : This property holds all the managed properties that our display template will have access to. The properties are organized in the key:value format. For example, if we wish to make use of the Author property, we will declare it as 'Author':'Author'. The value can be a list of managed properties, so if the first one is null, the mapping will be done using the second one, and so on. ContentTypeId : This property sets the content type of the display template. The specific value recognizes the file as a display template. TargetControlType : This property sets the target of the display template. In our example it is set to Content Web Parts , which means the search content web part and any other related search content web part. Other possible values are SearchBox , SearchHoverPanel , SearchResults , and so on. Since we wish to display the author and the last modified date of the document, let's add these two managed properties to the ManagedPropertyMapping property. Add the following snippet in the beginning of the property, as follows: <mso:ManagedPropertyMapping msdt_dt="string">'Author:'Author','LastModified':'LastModifiedTime',… </mso:ManagedPropertyMapping> We mapped the Author managed property to the Author key, and the LastModifiedTime managed property to the LastModified key. Next, we will discuss how to actually use the new properties. Getting the values of the new properties Using the newly added properties is done using plain old JavaScript. Scroll down a bit until you see the following opening div statement: <div id="TwoLines"> The div tag begins with what seems to be a comment markup (<!--), but if you look closer you should recognize that it is actually JavaScript. By using built-in methods and client object model code, display templates can get any information out of SharePoint, and of the outside world. The getItemValue method is in charge of getting content back based on a given managed property. That means if we wish to get the author of a result, and we set the key to the managed property to be Author, the following line of code will get it: var author = $getItemValue(ctx,"Author"); The same goes for the last modified date. We used the key LastModified for the managed property, and hence the following line of code will be used: var last = $getItemValue(ctx,"LastModified"); Add these two lines just above the closing comment statement markup (_#-->). Remember that each result is rendered using this display template, so the author and the last variables are unique for that one item that is being rendered.
Read more
  • 0
  • 0
  • 2923

article-image-debugging-sikuli-scripts
Packt
30 Jul 2013
3 min read
Save for later

Debugging Sikuli scripts

Packt
30 Jul 2013
3 min read
This is the last topic with test automation is the debugging of scripts. A portion of all time working on script development will be spent running the script trying to debug problems with the scripts to get them to run reliably. Once you have a collection of scripts that you run on a regular basis without supervision, identifying causes of errors can become much more difficult. There are two main techniques for debugging Sikuli scripts when running them in the test harness presented here. The first method is to look at the logs. If you look back over the test runner script, you can see that it logs a complete record of the console output to a file. These files end in .final.log. You can open these in your text editor, and see what your script did and get feedback about the errors. The errors in the logs will tell you what happened. For example, you might get something like this: This one is telling us that Sikuli couldn't find the requested image on the screen. Or, you might see errors with your Python code. In situations like this, it's handy to know that Sikuli scripts are just a collection of files in a directory. You can actually open it up and look at the images and Python code within it. Another handy technique is to record videos of your test runs. This allows you to review what happened during a test (passing or failing) to see what went wrong, or analyze the execution for possible improvements to execution speed. For Mac OS X, this can be done using QuickTime Player, which is included with the OS. For Windows or Linux, you will need to investigate a similar solution solution (the examples prepared for this book contain a working example for Windows), but the general technique should still apply. Let's see how this would work in practice. Firstly, we need to create two additional scripts, one to start recording and another to stop it. The script is broken into two parts, so they can be executed independently. Here's the startup script (see startcapture.sikuli): And here's the script to stop recording (see stopcapture.sikuli): These are then pretty easy to integrate with our test runner scripts (see runtests_withrecording.sikuli): Depending on your machine, you may also encounter some performance degradations when recording video along with your tests. To compensate, you can adjust the default amount of time that Sikuli will wait to find something from 5 seconds to 10 seconds, or more (you may need to experiment), by adding the following line to the end of your library.sikuli script: Summary This article helped you debug your Sikuli scripts either by looking at the logs or by recording videos of your test runs. Useful Links: Visual Studio 2008 Test Types Android Application Testing: Getting Started Python Testing: Installing the Robot Framework
Read more
  • 0
  • 0
  • 3144

article-image-using-glew
Packt
30 Jul 2013
9 min read
Save for later

Using GLEW

Packt
30 Jul 2013
9 min read
(For more resources related to this topic, see here.) Quick start – using GLEW You have now installed GLEW successfully and configured your OpenGL project in Visual Studio to use it. In this article, you will learn how to use GLEW by playing with a simple OpenGL program that displays a teapot. We will extend this program to render the teapot with toon lighting by using shader programs. To do this, we will use GLEW to set up the OpenGL extensions necessary to use shader programs. This example gives you a chance to experience GLEW to utilize a popular OpenGL extension. Step 1 – using an OpenGL program to display a teapot Consider the following OpenGL program that displays a teapot with a light shining on it: #include <GL/glut.h>void initGraphics(){glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);const float lightPos[4] = {1, .5, 1, 0};glLightfv(GL_LIGHT0, GL_POSITION, lightPos);glEnable(GL_DEPTH_TEST);glClearColor(1.0, 1.0, 1.0, 1.0);}void onResize(int w, int h){glMatrixMode(GL_PROJECTION);glLoadIdentity();glViewport(0, 0, w, h);gluPerspective(40, (float) w / h, 1, 100);glMatrixMode(GL_MODELVIEW);}void onDisplay(){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();gluLookAt(0.0, 0.0, 5.0,0.0, 0.0, 1.0,0.0, 1.0, 0.0);11Instant GLEWglutSolidTeapot(1);glutSwapBuffers();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);glutInitWindowSize(500, 500);glutCreateWindow("Teapot");initGraphics();glutDisplayFunc(onDisplay);glutReshapeFunc(onResize);glutMainLoop();return 0;} Create a new C++ console project in Visual Studio and copy the above code into the source file. On compiling and running this code in Visual Studio, you will see a window with a grey colored teapot displayed inside it as shown in the screenshot below: Let us briefly examine this OpenGL program and try to understand it. The main function shown below uses the GLUT API to create an OpenGL context, to create a window to render in and to set up the display function that is invoked on every frame. Instead of GLUT, you could also use other cross-platform alternatives such as the OpenGL Framework (GLFW) library or the windowing API of your platform. int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);glutInitWindowSize(500, 500);glutCreateWindow("Teapot");initGraphics();glutDisplayFunc(onDisplay);glutReshapeFunc(onResize);glutMainLoop();return 0;} Here, the call to glutInit creates an OpenGL context and the calls to glutInitDisplayMode, glutInitWindowSize, and glutCreateWindow help create a window in which to render the teapot. If you examine the initGraphics function, you can see that it enables lighting, creates a light at a given position in 3D space, and sets the background color to white. Similarly, the onResize function sets the size of the viewport based on the size of the rendering window. Passing a pointer to the onResize function as input to glutReshapeFunc ensures that GLUT calls onResize every time the window is resized. And finally, the onDisplay function does the main job of setting the camera and drawing a teapot. Passing a pointer to the onDisplay function as input to glutDisplayFunc ensures that GLUT calls onDisplayfunction every time a frame is rendered. Step 2 – using OpenGL extensions to apply vertex and fragment shaders One of the most common uses of GLEW is to use vertex and fragment shader programs in an OpenGL program. These programs can be written using the OpenGL Shading Language (GLSL). This was standardized in OpenGL 2.0. But, most of the versions of Windows support only OpenGL 1.0 or 1.1. On these operating systems, shader programs can be used only if they are supported by the graphics hardware through OpenGL extensions. Using GLEW is an excellent way to write portable OpenGL programs that use shader programs. The program can be written such that shaders are used when they are supported by the system, and the program falls back on simpler rendering methods when they are not supported. In this section, we extend our OpenGL program to render the teapot using toon lighting. This is a simple trick to render the teapot using cartoonish colors. We first create two new text files: one for the vertex shader named teapot.vert and another for the fragment shader named teapot.frag. You can create these files in the directory that has your OpenGL source program. Copy the following code to the teapot.vert shader file: varying vec3 normal, lightDir;void main(){lightDir = normalize(vec3(gl_LightSource[0].position));normal = normalize(gl_NormalMatrix * gl_Normal);gl_Position = ftransform();} Do not worry if you do not know GLSL or cannot understand this code. We are using this shader program only as an example to demonstrate the use of OpenGL extensions. This shader code applies the standard transformations on vertices. In addition, it also notes down the direction of the light and the normal of the vertex. These variables are passed to the fragment shader program which is described next. Copy the following code to the teapot.frag shader file: varying vec3 normal, lightDir;void main(){float intensity;vec3 n;vec4 color;n = normalize(normal);intensity = max(dot(lightDir, n), 0); if (intensity > 0.97)color = vec4(1, .8, .8, 1.0);else if (intensity > 0.25)color = vec4(.8, 0, .8, 1.0);elsecolor = vec4(.4, 0, .4, 1.0);gl_FragColor = color;} Again, do not worry if you do not understand this code. This fragment shader program is executed at every pixel that is generated for display. The result of this program is a color, which is used to draw that pixel. This program uses the light direction and the normal passed from the vertex shader program to determine the light intensity at a pixel. Based on the intensity value, it picks one of three possible shades of purple to color the pixel. By employing these shader programs, the teapot is rendered in toon lighting like this: However, to get this output our OpenGL program needs to be modified to compile and load these shader programs. Step 3 – including the GLEW header file To be able to call the GLEW API, you need to include the glew.h header file in your OpenGL code. Make sure it is placed above the include files of gl.h, glext.h, glut.h, or any other OpenGL header files. Also, if you include glew.h, you don't really need to include gl.h or glext.h. This is because GLEW redefines the types and function declarations that are in these OpenGL header files. #include <GL/glew.h>#include <GL/glut.h> Step 4 – initializing GLEW GLEW should be initialized before calling any of its other API functions. This can be performed by calling the glewInit function. Ensure that this is called after an OpenGL context has been created. For example, if you are using GLUT in your OpenGL program, call glewInit only after a GLUT window has been created. The code shown below initializes GLEW: GLenum err = glewInit();if (GLEW_OK != err){printf("GLEW init failed: %s!n", glewGetErrorString(err));exit(1);}else{printf("GLEW init success!n");} The call to glewInit does the hard work of determining all the OpenGL extensions that are supported on your system. It returns a value of GLEW_OK or GLEW_NO_ERROR if the initialization was successful; otherwise, it returns a different value. For example, if glewInit is called before an OpenGL context was created, it returns a value of GLEW_ERROR_NO_GL_VERSION. You can find out the cause of a GLEW error by passing the return value of glewInit to the function glewGetErrorString as shown above. This returns a human-readable string that explains the error. Step 5 – checking if an OpenGL extension is supported New or enhanced functionality in the OpenGL API is provided by the means of an extension. This typically means that new data types and API functions are added to the OpenGL specification. Details of the name and functionality of any extension can be found in the OpenGL. In our example, we want our OpenGL program to be able to use GLSL vertex and fragment shaders. This functionality has been provided using extensions that are named GL_ARB_vertex_shader and GL_ARB_fragment_shader. These extensions provide functions to create shader objects, set the shader source code, compile it, link it, and use them with an OpenGL program. Some of the functions provided by this extension are listed below: glCreateShaderObjectARB();glShaderSourceARB();glCompileShaderARB();glCreateProgramObjectARB();glAttachObjectARB();glLinkProgramARB();glUseProgramObjectARB(); To be able to use these functions in our OpenGL program, we first check if the extension is enabled in our system. Depending on the graphics hardware and drivers on your system, not every OpenGL extension might be available and usable on your system. For example, most versions of Windows support only OpenGL 1.0 or 1.1. The drivers supplied by graphics hardware vendors, such as NVIDIA or AMD for example, might support more recent versions of OpenGL and OpenGL extensions. Every OpenGL extension has a name of the form GL_VENDOR_extension_name. The VENDOR may be NV, ATI, APPLE, EXT, ARB, or any such supported vendor name. An extension created by a single vendor is called a vendor-specific extension. If it is created by many vendors, it is called a multivendor extension. If many users find an extension to be a good enhancement, it is promoted to an ARB-approved extension. Such extensions might be integrated into future versions of OpenGL as a core feature. To check for an extension using GLEW, you check if a global boolean variable named GLEW_VENDOR_extension_name is set to true. These variables are defined and their values are set when you initialize GLEW using glewInit. So, to test if vertex and fragment shaders are supported, we add the following code: if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader){printf("No GLSL supportn");exit(1);} In this example, we exit the program if these extensions are not supported. Alternatively, you could write the program so that it switches to a simpler or alternate rendering method if the extension you want is not supported. Summary This article provided you the details to use GLEW with OpenGL code using a simple example of teapot rendering. Resources for Article : Further resources on this subject: Introduction to Modern OpenGL [Article] Tips and Tricks for Getting Started with OpenGL and GLSL 4.0 [Article] Android Native Application API [Article]
Read more
  • 0
  • 0
  • 9221

article-image-command-line
Packt
30 Jul 2013
19 min read
Save for later

The Command Line

Packt
30 Jul 2013
19 min read
(For more resources related to this topic, see here.) VSTest.Console utility In Visual Studio 2012, the VSTest.Console command line utility is used for running the automated unit test and coded UI test. VSTest.Console is an optimized replacement for MSTest in Visual Studio 2012. There are multiple options for the command line utility that can used in any order with multiple combinations. Running the command VSTest.Console /? at the command prompt shows the summary of available options and the usage message. These options are shown in the following screenshot: Running tests using VSTest.Console Running the test from the command prompt requires the expected parameters to be passed based on the options used along with the command. Some of the options available with VSTest.Console command are explained in the next few sections: The /Tests option This command is used to select particular tests from the list of tests in the test file. Specify the test names as parameters to the command, and separate the tests using commas when multiple tests are to be run. The next screenshot shows a couple of test methods that run from the test file: The output shows the Test Run result for each of the tests along with the messages, if any. The summary of the tests is also shown at the end of the results sections with the time taken for the test execution. The /ListTests option This command is used to list all available tests within the test file. The following screenshot lists the tests from one of the Test Project file: The next one is another command line utility, MSTest, which is used to run any automated tests. MSTest utility To access the MSTest tool, add the Visual Studio install directory to the path or open the Visual Studio Group from the Start menu, and then open the Tools section to access the Visual Studio command prompt. Use the command MSTest from the command prompt. The MSTest command expects the name of the test as parameter to run the test. Just type MSTest /help or MSTest /? at the Visual Studio command prompt to get help and find out more about options. The following table lists the different parameters that can be used with MSTest and the description of each parameter and its usage: Option Description /help This option displays the usage message for all parameters type /? or /h. /nologo This option disables the display of startup banner and the copyright message. /testcontainer:[file name] This option loads a file that contains tests; multiple test files can be specified to load multiple tests from the files, for example: /tescontainer:mytestproject.dll/testcontainer:loadtest1.loadtest /maxpriority:[priority] /minpriority:[priority] This option execute the tests with priority less than or equal to the value: /minpriority:0 /maxpriority:2. /category This filter is used to select tests and run, based on the category of each test. We can use logical operators (& and !) to construct the filters, or we can use the logical operators (| and &!) to filter the tests.   /category:Priority1 - any tests with category as priority1.   /category: "Priority1&MyTests"- any tests with multiple categories as priority1 and Mytests.   /category: "Priority1|Mytests" - Multiple tests with category as either Priority1 or MyTests.   /category:"Priority1&!MyTests" - Priority1 tests that do not have category MyTests /testmetadata:[file name] This option loads a metadata file. For example, /testmetadata:testproject1.vsmdi. /testsettings:[file name] This option uses the specified test settings file. For example, /testsettings:mysettings.testsettings. /resultsfile:[file name] This option saves the Test Run results to the specified file. for example, /resultsfile:c:tempmyresults.trx. /testlist:[test list path] The test list to run as specified in the metadata file; you can specify this option multiple times to run more than one test list. For example, /testlist:checkintests/clientteam. /test:[file name] This is the name of a test to be run; you can specify this option multiple times to run more than one test. /unique This option runs a test only if one unique match is found for any given /test. /noisolation This option runs a test within the MSTest.exe process. This choice improves Test Run speed, but increases risk to the MsTest process. /noresults This option does not save the Test Results in a TRX file; the choice improves Test Run speed, but does not save the Test Run results /detail:[property id] This parameter is used for getting value of additional property along with the test outcome. For example, the following command with the property is to get the error message from the Test Result: /detail:errormessage Running a test from the command line MSTest is only for automated tests. Even if the command is applied to a manual test, the tool will remove the non-automated test from the Test Run. The /testcontainer option The /testcontainer option requires the filename as parameter which contains information about tests that must be run. The /testcontainer file is an assembly that contains all the tests under the project, and each of the projects under a solution has its own container for the tests within the projects. For example, the next screenshot shows the list of tests within the container unittestproject1.dll. MSTest executes all the tests within the container and shows the result as well. The summary of the Test Result is as shown in the next screenshot: First, the MSTest will load all the tests within the project, then start executing them one by one. The result of each Test Run is shown but the detailed Test Run information is stored in the test trace file. The trace file can be loaded in Visual Studio to get the details of the Test Result. The /testmetadata option The /testmetadata option is used for running tests in multiple Test Projects under a solution. This is based on the metadata file, which is an XML file that has the list of all the tests created under the solution. The /testcontainer option is specific to a Test Project, whereas /testmetadata is for multiple test containers with the flexibility of choosing tests from each container. The /test option There are instances where running all the tests within a test container is not required. To specify only the required tests, use the /test option with the /testmetadata option or the /testcontainer option. For example, the following command runs only the CodedUITest1 test from the list of all tests: The /test option can be used along with /testmetadata or /testcontainer, but not both. There are different usages for the /test option: Any number of tests can be specified using the /test option multiple times against the /testmetadata or /testcontainer option. The name used against the /test option is the search keyword of the fully qualified test names. For example, if there are test names with fully qualified names such as: UnitTestProject1.UnitTest1.CalculateTotalPriceTest UnitTestProject1.UnitTest1.CalculateTotalPricewithTaxTest UnitTestProject1.UnitTest1.GetTotalPriceTest And if the command contains the option /test:UnitTestProject1, then all of the preceding three tests will run as the name contains the UnitTestProject1 string in it. Even though we specify only the name to the /test option, the result will display the fully qualified name of the tests run in the results window. The /unique option The /unique option will make sure that only one test which matches the given name, is run. In the preceding examples, there are different tests with the string UnitTestProject1 in its fully qualified name. Running the following command executes all the preceding tests: mstest /testcontainer:c:SatheeshSharedAppsEmployeeMaintenance UnitTestProject1bindebugunittestproject1.dll /test:Unittestproject1 But if the /unique option is specified along with the preceding command, the MSTest utility will return the message saying that more than one test was found with the same name. It means that the test will be successful only if the test name is unique. The following command will execute successfully as there is only one test with the name GetTotalItemPriceTest. The /noisolation option The /noisolation option runs the tests within the MStest.exe process. This choice improves the Test Run speed, but increases risk to the MSTest.exe process. Usually, the tests are run in a separate process that is allocated with separate memory from the system. By launching the MSTest.exe process with the /noisolation option, we avoid having a separate process created for the test. The /testsettings option The /testsettings option is used to specify the Test Run to use a specific test settings file. If the settings file is not specified, MSTest uses the default settings file. The following example forces the test to use the TestSettings1 settings file: The /resultsfile option In all the command executions, the MSTest utility stores the Test Results to a trace file. By default, the trace file name is assigned by MSTest using the login user ID, the machine name, and the current date and time. This can be customized to store the Test Results in a custom trace file using the /resultsfile option. For example, the next screenshot shows the custom trace file named as customtestresults.trx: The preceding screenshot shows the Test Results stored at the c:Satheesh location in the results file, customtestresult.trx. The /noresults option The /noresults option informs the MSTest application not to store the Test Results to the TRX file. This option increases the performance of the test execution. The /nologo option The /nologo option is to inform the MSTest tool not to display the copyright information that is usually shown at the beginning of the Test Run. The /detail option The /detail option is used for collecting the property values from each Test Run result. Each Test Result provides information about the test such as error messages, start time, end time, test name, description, test type, and many more. The /detail option is useful to get the property values after the Test Run. For example, the following screenshot shows the start and end time of the Test Run, and also the type of the Test Run: The /detail option can be specified multiple times to get multiple property values after the Test Run. Publishing Test Results Publishing Test Results is valid only if Team Explorer is installed, and if Visual Studio is connected to the Team Foundation Server (TFS). This is to publish the test data and results to the TFS Team Project. Please refer to Microsoft Developer Network (MSDN) for more information on installing and configuring TFS and Team Explorer. Test Results can be published using the command line utility and the various options along with the utility. The /publish option with MSTest will first run the test, and then set the flavor and platform for the test before publishing the data to the TFS. Some of these options are mandatory for publishing the Test Run details. The following are the different publishing options for the command line MSTest tool: The /publish option The /publish option should be followed by the uniform resource identifier (URI) of the TFS, if the TFS is not registered in the client. If it is registered, just use the name of the server to which the Test Result has to be published, as shown in the following command: /publish:[server name] Refer to the following examples: If the TFS Server is not registered in the client, then: /publish:http://MyTFSServer() If the TFS Server is registered with the client, then: /publish:MyTFSServer The /publishbuild option The /publishbuild option is used for publishing the builds. The parameter value is the unique name that identifies the build from the list of scheduled builds. The /flavor option Publishing the Test Rresults to TFS requires /flavor as mandatory. Flavor is a string value that is used in combination with the platform name, and should match with the completed build that can be identified by the /publishbuild option. The MSTest command will run the test, and then set the flavor and platform properties, before publishing the Test Run results to the TFS: /flavour:[flavour string value] For example: /flavor:Release /flavor:Debug The /platform option This is a mandatory string value used in combination with the /flavor option which should match the build option. /platform:[string value] For example: /platform:Mixed Platforms /platform:NET /platform:Win32 The /publishresultsfile option MSTest stores all the Test Results in the default trace files with the extension .trx. Using the /publishresultsfile option, the Test Results file can be published to TFS using the output/trace option. The name of the file is the input to this option. If the value is not specified, MSTest will publish the current Test Run trace file to TFS. /publishresultsfile:[file name string] For example, to publish the current Test Run trace file, use the /publishresultsfile option. To publish the Test Result, one can use a combination of different options we saw in previous sections, along with the option /publishresultsfile. The Test Results from the results file are published to the build output of the solution. The steps involved in publishing are to create the test, create a build definition, build the solution, execute the test, and then publish the result to the build output. Step 1 – create/use existing Test Project The following screenshot contains the solution EmployeeMaintenance. The solution contains a Test Project WebAndLoadTestProject1 with a web test WebTest2. The following screenshot shows the Test Project named WebAndLoadTestProject1: Step 2 – running the test On running the web test, by default the Test Result is stored in the trace file <file name>.trx. Step 3 – creating a build The /build service in Team Foundation Server has to be configured with a controller and agents. Each build controller manages a set of build agents. Unfortunately, the steps and the details behind creating the build types will not be covered in this article as it would be too long to discuss it. The following screenshot shows the /build service configured with controller and agents: To create the build definition using the Team Explorer, navigate to the Build definitions in Builds folder, under Team Project. Select new build definition, and then configure the options by choosing the projects in TFS and the local folder. In one of the steps, you can see the following screenshot for selecting the project and setting the configuration information for the build process: There are different configuration sections such as Required, Basic, and, Advanced, from where the project can be selected to include as part of this build definition setting such as build file formats, Agents Settings, work item creation on build failure, and other configurations. Step 4 – building the project Now that the project is created, configurations and properties are set, and we are ready to run the test, we will build and publish the Test Results. Select the New build definition and start the build queue process. The build service takes care of building the solution by applying the build definition, and on completion the result section shows the build summary. Step 5 – publishing the result So far, the test is run and the result is saved in the trace file, and also we have built the project using the build definition. The Test Run results should be published to the build. There are multiple options used for publishing the Test Results using the MSTest command line tool. The following command in the next screenshot publishes the Test Result to the specified build: The command line options used in the preceding screenshot shows the Test Result trace file, TFS Team Project, and build against which the Test Result should be published. The command line also has the platform and the flavor values matching the build configurations. After publishing the Test Results, if you open the build file, the test information along with the build summary is shown in the build summary. The information also contains a link to the trace file. TCM command line utility TCM is the command line utility used for importing automated tests to the Test Plan, running the test from the Test Plan, and then viewing a of tests and IDs corresponding to them. This utility is very useful if the IDE is not available. The /help or /? command is used to get the syntax and parameters for the tool. Following are the syntax and parameters for the tcm.exe tool: Importing tests to a Test Plan There wasn't any test case for the unit test, and running the test case was also from Visual Studio IDE. This section explains how to import the tests to a Test Plan and create the test cases automatically while importing through the command line. The Test Plans are created using the Test Manager to group the Test Suites and test cases. The following screenshot shows a few Test Plans created for the Team Project TeamProject1: The EmployeeMaintenance solution contains the unit Test Project UnitTestProject1 with a few methods out of which there are methods such as CalculateTotalPriceTest() and CalculateTotalPricewithTaxTest() with their category defined as TotalPrice. So far there are no test cases defined in any of the Test Plans in the Test Manger for these tests. Refer to the following screenshot: For any tests created using Visual Studio, the TCM utility can be used to import it to the Test Plan in Test Manager as test cases. The following command imports all tests with the category defined as TotalPrice from the UnitTestProject1 assembly into the Team Project TeamProject1. The category is defined to the tests to group it from all other available tests within the assembly. Refer to the following screenshot: The command execution result shows the summary of the import, along with the names of the tests matching the command parameters. Connect to the TeamProject1 using Test Manager and open any of the Test Plans within the project. On the Contents tab under the Plan option in Testing Center, click on Add from the toolbar in Test Suite section on the right. This will open up a new window to search for any available test cases to add to the Test Suite. By default, the Test Plan is the Test Suite, if no other Test Suite is created for the plan. In the new window, just click on the Run option to perform the default search with default parameters. You may notice that the search result shows two test cases in the name of the test methods which were imported from the Test Project. The test cases are named after the test method itself. Select either or both of the test cases and add them to the Test Suite. After adding the test case to the Test Suite and Test Plan, open the test case using the Open toolbar option. There won't be any step except the name of the test case and few other details. Include the details of the test steps to the test case, if required. Running tests in a Test Plan The tests cases associated with the tests can be run using the TCM command line utility without using the IDE. Whenever a test is run using the TCM, it requires additional information such as the environment and roles within the environment. Running the test case using TCM requires Test Points or the Test Suite, and the configuration information. TCM requires the IDs of the Test Plan, Test Suite, and configuration. The TCM command line can be used to retrieve all these details. To list all configurations from the Team Project, the TCM command is like the following result: The following is the command and output for listing all the Test Plans within the Team Project: To list all the Test Suites within the Plan, use the following TCM command with the options as shown in the next screenshot along with the Plan ID, collection, and the Team Project name. Use the Plan ID from the previous command output: Use the Config ID, Plan ID, and the Suite ID collected by using the TCM utility from the collection and the Team Project to run the test. This will create a run as shown in the following screenshot: The Test Run is created and the result can be viewed in Test Manager for analysis. Open the Test Manager and select the option Test under Testing Center. Select Analyze Test Runs from the menu bar. The Analyze Test Runs window shows the Test Runs for the Test Plan. The following screenshot shows a detailed view of the Test Run. The test is still in progress but you can see the test cases and the other details provided at the command: The Test Agent needs to be set up to run as a process instead of a service to run the automated tests to interact with desktop. Summary This article explained the use of multiple command line utilities such as VSTest. Console, MSTest, and TCM for running the tests. These tools are very handy when there is no IDE. Lots of features are covered using the command line utility when compared to the earlier versions of Visual Studio. The VSTest.Console utility comes with multiple options to run automated tests such as unit tests and Coded UI tests. The MSTest utility provides options for backward compatibility along with multiple options to run automated tests and publish the results to the Team Foundation Server. The TCM utility is used for importing tests and creating test cases automatically to Test Plans. This utility is very useful, and saves lot of manual activities with Test Manager. Overall these utilities provide lot of features at the command line, and remove the IDE dependency. Resources for Article: Further resources on this subject: Connecting to Microsoft SQL Server Compact 3.5 with Visual Studio [Article] Visual Studio 2010 Test Types [Article] Displaying SQL Server Data using a Linq Data Source [Article]
Read more
  • 0
  • 0
  • 8043
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-arrays-objects
Packt
30 Jul 2013
11 min read
Save for later

From arrays to objects

Packt
30 Jul 2013
11 min read
(For more resources related to this topic, see here.) An array is just a list of values. Each value has an index (a numeric key) that starts from zero and increments by one for each value. > var myarr = ['red', 'blue', 'yellow', 'purple']; > myarr; ["red", "blue", "yellow", "purple"]. > myarr[0]; "red" > myarr[3]; "purple" If you put the indexes in one column and the values in another, you'll end up with a table of key/value pairs shown as follows: Key Value 0 red 1 blue 2 yellow 3 purple An object is similar to an array, but with the difference that you define the keys yourself. You're not limited to using only numeric indexes and you can use friendlier keys, such as first_name, age, and so on. Let's take a look at a simple object and examine its parts: var hero = { breed: 'Turtle', occupation: 'Ninja' }; You can see that: The name of the variable that refers to the object is hero Instead of [ and ], which you use to define an array, you use { and } for objects You separate the elements (called properties) contained in the object with commas The key/value pairs are divided by colons, as in key: value The keys (names of the properties) can optionally be placed in quotation marks. For example, these are all the same: var hero = {occupation: 1}; var hero = {"occupation": 1}; var hero = {'occupation': 1}; It's recommended that you don't quote the names of the properties (it's less typing), but there are cases when you must use quotes: If the property name is one of the reserved words in JavaScript  If it contains spaces or special characters (anything other than letters, numbers, and the _ and $ characters) If it starts with a number In other words, if the name you have chosen for a property is not a valid name for a variable in JavaScript, then you need to wrap it in quotes. Have a look at this bizarre-looking object: var o = { $omething: 1, 'yes or no': 'yes', '!@#$%^&*': true }; This is a valid object. The quotes are required for the second and the third properties, otherwise you'll get an error. Later in this chapter, you'll see other ways to define objects and arrays in addition to [] and {}. But first, let's introduce this bit of terminology: defining an array with [] is called array literal notation, and defining an object using the curly braces {} is called object literal notation. Elements, properties, methods, and members When talking about arrays, you say that they contain elements. When talking about objects, you say that they contain properties. There isn't any significant difference in JavaScript; it's just the terminology that people are used to, likely from other programming languages. A property of an object can point to a function, because functions are just data. Properties that point to functions are also called methods. In the following example, talk is a method: var dog = { name: 'Benji', talk: function () { alert('Woof, woof!'); } }; As you have seen in the previous chapter, it's also possible to store functions as array elements and invoke them, but you'll not see much code like this in practice: > var a = []; > a[0] = function (what) { alert(what); }; > a[0]('Boo!'); You can also see people using the word members to refer to properties of an object, most often when it doesn't matter if the property is a function or not. Hashes and associative arrays In some programming languages, there is a distinction between: A regular array, also called an indexed or enumerated array (the keys are numbers) An associative array, also called a hash or a dictionary (the keys are strings) JavaScript uses arrays to represent indexed arrays and objects to represent associative arrays. If you want a hash in JavaScript, you use an object. Accessing an object's properties There are two ways to access a property of an object: Using the square bracket notation, for example hero['occupation'] Using the dot notation, for example hero.occupation The dot notation is easier to read and write, but it cannot always be used. The same rules apply as for quoting property names: if the name of the property is not a valid variable name, you cannot use the dot notation. Let's take the hero object again: var hero = { breed: 'Turtle', occupation: 'Ninja' }; Accessing a property with the dot notation: > hero.breed; "Turtle" Accessing a property with the bracket notation: > hero['occupation']; "Ninja" Accessing a non-existing property returns undefined: > 'Hair color is ' + hero.hair_color; "Hair color is undefined" Objects can contain any data, including other objects: var book = { name: 'Catch-22', published: 1961, author: { firstname: 'Joseph', lastname: 'Heller' } }; To get to the firstname property of the object contained in the author property of the book object, you use: > book.author.firstname; "Joseph" Using the square brackets notation: > book['author']['lastname']; "Heller" It works even if you mix both: > book.author['lastname']; "Heller" > book['author'].lastname; "Heller" Another case where you need square brackets is when the name of the property you need to access is not known beforehand. During runtime, it's dynamically stored in a variable: > var key = 'firstname'; > book.author[key]; "Joseph" Calling an object's methods You know a method is just a property that happens to be a function, so you access methods the same way as you would access properties: using the dot notation or using square brackets. Calling (invoking) a method is the same as calling any other function: you just add parentheses after the method name, which effectively says "Execute!". > var hero = { breed: 'Turtle', occupation: 'Ninja', say: function () { return 'I am ' + hero.occupation; } }; > hero.say(); "I am Ninja" If there are any parameters that you want to pass to a method, you proceed as with normal functions: > hero.say('a', 'b', 'c'); Because you can use the array-like square brackets to access a property, this means you can also use brackets to access and invoke methods: > hero['say'](); This is not a common practice unless the method name is not known at the time of writing code, but is instead defined at runtime: var method = 'say'; hero[method](); Best practice tip: no quotes (unless you have to) Use the dot notation to access methods and properties and don't quote properties in your object literals. Altering properties/methods JavaScript allows you to alter the properties and methods of existing objects at any time. This includes adding new properties or deleting them. You can start with a "blank" object and add properties later. Let's see how you can go about doing this. An object without properties is shown as follows: > var hero = {}; A "blank" object In this section, you started with a "blank" object, var hero = {};. Blank is in quotes because this object is not really empty and useless. Although at this stage it has no properties of its own, it has already inherited some. You'll learn more about own versus inherited properties later. So, an object in ES3 is never really "blank" or "empty". In ES5 though, there is a way to create a completely blank object that doesn't inherit anything, but let's not get ahead too much. Accessing a non-existing property is shown as follows: > typeof hero.breed; "undefined" Adding two properties and a method: > hero.breed = 'turtle'; > hero.name = 'Leonardo'; > hero.sayName = function () { return hero.name; }; Calling the method: > hero.sayName(); "Leonardo" Deleting a property: > delete hero.name; true Calling the method again will no longer find the deleted name property: > hero.sayName(); "undefined" Malleable objects You can always change any object at any time, such as adding and removing properties and changing their values. But, there are exceptions to this rule. A few properties of some built-in objects are not changeable (for example, Math.PI, as you'll see later). Using the this value In the previous example, the sayName() method used hero.name to access the name property of the hero object. When you're inside a method though, there is another way to access the object the method belongs to: by using the special value this. > var hero = { name: 'Rafaelo', sayName: function () { return this.name; } }; > hero.sayName(); "Rafaelo" So, when you say this, you're actually saying "this object" or "the current object". Constructor functions There is another way to create objects: by using constructor functions. Let's see an example: function Hero() { this.occupation = 'Ninja'; } In order to create an object using this function, you use the new operator, like this: > var hero = new Hero(); > hero.occupation; "Ninja" A benefit of using constructor functions is that they accept parameters, which can be used when creating new objects. Let's modify the constructor to accept one parameter and assign it to the name property: function Hero(name) { this.name = name; this.occupation = 'Ninja'; this.whoAreYou = function () { return "I'm " + this.name + " and I'm a " + this.occupation; }; } Now you can create different objects using the same constructor: > var h1 = new Hero('Michelangelo'); > var h2 = new Hero('Donatello'); > h1.whoAreYou(); "I'm Michelangelo and I'm a Ninja" > h2.whoAreYou(); "I'm Donatello and I'm a Ninja" Best practice By convention, you should capitalize the first letter of your constructor functions so that you have a visual clue that this is not intended to be called as a regular function. If you call a function that is designed to be a constructor but you omit the new operator, this is not an error, but it doesn't give you the expected result. > var h = Hero('Leonardo'); > typeof h; "undefined" What happened here? There is no new operator, so a new object was not created. The function was called like any other function, so h contains the value that the function returns. The function does not return anything (there's no return), so it actually returns undefined , which gets assigned to h. In this case, what does this refer to? It refers to the global object. The global object You have already learned a bit about global variables (and how you should avoid them). You also know that JavaScript programs run inside a host environment (the browser for example). Now that you know about objects, it's time for the whole truth: the host environment provides a global object and all global variables are accessible as properties of the global object. If your host environment is the web browser, the global object is called window. Another way to access the global object (and this is also true in most other environments) is to use this outside a constructor function, for example in the global program code outside any function. As an illustration, you can declare a global variable outside any function, such as: > var a = 1; Then, you can access this global variable in various ways: As a variable a As a property of the global object, for example window['a'] or window.a As a property of the global object referred to as this: > var a = 1; > window.a; 1 > this.a; 1 Let's go back to the case where you define a constructor function and call it without the new operator. In such cases, this refers to the global object and all the properties set to this become properties of window. Declaring a constructor function and calling it without new returns "undefined" : > function Hero(name) { this.name = name; } > var h = Hero('Leonardo'); > typeof h; "undefined" > typeof h.name; TypeError: Cannot read property 'name' of undefined Because you had this inside Hero, a global variable (a property of the global object) called name was created: > name; "Leonardo" > window.name; "Leonardo" If you call the same constructor function using new, then a new object is returned and this refers to it: > var h2 = new Hero('Michelangelo'); > typeof h2; "object" > h2.name; "Michelangelo" The built-in global functions can also be invoked as methods of the window object. So, the following two calls have the same result: > parseInt('101 dalmatians'); 101 > window.parseInt('101 dalmatians'); 101 And, when outside a function called as a constructor (with new), also: > this.parseInt('101 dalmatians'); 101
Read more
  • 0
  • 0
  • 1504

article-image-first-steps-r
Packt
30 Jul 2013
6 min read
Save for later

First steps with R

Packt
30 Jul 2013
6 min read
(For more resources related to this topic, see here.) Obtaining and installing R The way to obtain R is downloading it from the CRAN website (http://www.r-project.org/). The Comprehensive R Archive Network (CRAN) is a network of FTP and web servers around the world that stores identical, up-to-date versions of code and documentation for R. The CRAN is directly accessible from the R website and on such website it is also possible to find information about R, some technical manuals, the R journal, and details about the packages developed for R and stored on the CRAN repositories. The functionalities of the R environment can then also be expanded thanks to software libraries which can be installed and recalled if needed. These libraries or packages are a collection of source code and other additional files that, when installed in R, allow the user to load them in the workspace via a call to the library() function. An example of code to load the package lattice may be found as follows: > library(lattice) An R installation contains one or more libraries of packages. Some of these packages are part of the basic installation and are loaded automatically as soon as the session is started. Other can be installed from the CRAN, the official R repository, or downloaded and installed manually. Interacting with the console As soon as you will start R, you will see that a workspace is open; you can see a screenshot of the R Console window in the image below. The workspace is the environment in which you are working, where you will load your data, and create your variables. The screen prompt > is the R prompt that waits for commands. On the starting screen, you can either type any function, command, or you can use R to perform basic calculation. R uses the usual symbols for addition (+), subtraction (-), multiplication (*), division (/), and exponentiation (^). Parentheses ( ) can be used to specify the order of operations. R also provides %% for taking the modulus and %/% for integer division. Comments in R are defined by the character #, so everything after such character up to the end of the line will be ignored by R. R has a number of built-in functions, for example, sin(x), cos(x), tan(x), (all in radians), exp(x), log(x), and sqrt(x). Some special constants such as pi are also pre-defined. You can see an example of the use of such function in the following code: > exp(2.5)[1] 12.18249 Understanding R objects In every computer language, variables provide a means of accessing the data stored in memory. R does not provide direct access to the computer’s memory but rather provides a number of specialized data structures called objects. These objects are referred to through symbols or variables. Vectors The basic object in R is the vector; even scalars are vectors of length one. Vectors can be thought of as a series of data of the same class. There are six basic vector type (called atomic vectors): logical, integer, real, complex, string (or character), and raw. Integer and real represent numeric objects; logicals are Boolean data type with possible value TRUE or FALSE. Among such atomic vectors, the more common ones are logical, string, and numeric (integer and real). There are several ways to create vectors. For instance the operator : (colon) is a sequence-generating operator, it creates sequences by incrementing or decrementing by one. > 1:10 [1] 1 2 3 4 5 6 7 8 9 10> 5:-6 [1] 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6 If the interval between the numbers is not one, you can use the seq() function. Here an example > seq(from=2, to=2.5, by=0.1)[1] 2.0 2.1 2.2 2.3 2.4 2.5 One of the more important features of R is the possibility to use entire vector as arguments of functions, thus avoiding the use of cyclic loops. Most of the functions in R allow the use of vector as argument, as example the use of some of these functions is reported as follows > x <- c(12,10,4,6,9)> max(x)[1] 12> min(x)[1] 4> mean(x)[1] 8.2 Matrices and arrays In R, the matrix notation is extended to elements of any kind, so in example it is possible to have a matrix of character strings. Matrices and arrays are basically vectors with a dimension attribute. The function matrix() may be used to create matrices. By default, such function creates the matrix by column; as alternative it is possible to specify to the function to build the matrix by row: > matrix(1:9,nrow=3,byrow=TRUE) [,1] [,2] [,3][1,] 1 2 3[2,] 4 5 6[3,] 7 8 9 Lists A list in R is a collection of different objects. One of the main advantages of lists is that the object contained within a list may be of different type, for example, numeric and character values. In order to define a list, you simply will need to provide the object that you want to include as argument of the function list(). Data frame A data frame corresponds to a data set; it is basically a special list in which the elements have the same length. Elements may be different type in different columns, but within the same column all the elements are of the same type. You can easily create data frames using the function data.frame(), and a specific column can be recall using the operator $. Top features you’ll want to know about In addition to the basic object creation and manipulation, many more complex tasks can be performed with R, spanning from data manipulation, programming, statistical analysis and the realization of very high quality graphs. Some of the most useful features are Data input and output Flow control (for, if…else, while) Create your own functions Debugging functions and handling exceptions Plotting data Summary In this article we saw what is R, how to obtain and install R, and how to interacting with the console. We also saw at few R objects and also looked at the top features you would want to know about Resources for Article: Further resources on this subject: Organizing, Clarifying and Communicating the R Data Analyses [Article] Customizing Graphics and Creating a Bar Chart and Scatterplot in R [Article] Graphical Capabilities of R [Article]
Read more
  • 0
  • 0
  • 6724

article-image-digging-architecture
Packt
30 Jul 2013
31 min read
Save for later

Digging into the Architecture

Packt
30 Jul 2013
31 min read
(For more resources related to this topic, see here.) The big picture A very short description of a WaveMaker application could be: a Spring MVC server running in a Java container, such as Tomcat, serving file and JSON requests for a Dojo Toolkit-based JavaScript browser client. Unfortunately, such "elevator" descriptions can create more questions than they answer. For starters, although we will often refer to it as "the server," the WaveMaker server might be more aptly called an application server in most architectures. Sure, it is possible to have a useful application without additional servers or services beyond the WaveMaker server, but this is not typical. We could have a rich user interface to read against some in memory data set, for example. Far more commonly, the Java services running in the WaveMaker server are calling off to other servers or services, such as relational databases and RESTful web services. This means the WaveMaker server is often the middle or application tier server of a multi-tier application's architecture. Yet at the same time, the WaveMaker server can be eliminated completely. Applications can be packaged for uploading to PhoneGap build, http://build.phonegap.com/,directly from WaveMaker Studio. Both PhoneGap and the associated Apache project Cordova, http://cordova.apache.org,provide APIs to enable JavaScript to access native device functionality, such as capturing images with the camera and obtaining GPS location information. Packaged up and installed as a native application, the JavaScript files are loaded from the devices, file system instead of being downloaded from a server via HTTP. This means there is no origin domain to be constrained by. If the application only uses web services, or otherwise doesn't need additional services, such as database access, the WaveMaker server is neither used nor needed. Just because an application isn't installed on a mobile device from an app store doesn't mean we can't run it on a mobile device. Browsers on mobile devices are more capable than ever before. This means our client could be any device with a modern browser. You must also consider licensing in light of the bigger picture. WaveMaker, WaveMaker Studio, and the applications create with the Studio are released under the Apache 2.0 license, http://www.apache.org/licenses/LICENSE-2.0. The WaveMaker project was first released by WaveMaker Software in 2007. In March 2011, VMware (http://vmware.com) acquired the WaveMaker project. It was under VMware that WaveMaker 6.5 was released. In April 2013, Pramati Technlogies (http://pramati.com) acquired the assets of WaveMaker for its CloudJee (http://cloudjee.com) platform. WaveMaker continues to be developed and released by Pramati Technologies. Now that we understand where our client and server sit in the larger world, we will be primarily focused within and between those two parts. The overall picture of the client and server looks as shown in the following diagram: We will examine each piece of this diagram in detail during the course of this book. We shall start with the JavaScript client. Getting comfortable with the JavaScript client The client is a JavaScript client that runs in a modern browser. This means that most of the client, the HTML and DOM nodes that the browser interfaces with specifically, are created by JavaScript at runtime. The application is styled using CSS, and we can use HTML in our applications. However, we don't use HTML to define buttons and forms. Instead, we define components, such as widgets, and set their properties. These component class names and properties are used as arguments to functions that create DOM nodes for us. Dojo Toolkit To do this, WaveMaker uses the Dojo Toolkit, http://dojotoolkit.org/. Dojo, as it is generally referred to, is a modular, cross-browser, JavaScript framework with three sections. Dojo Core provides the base toolkit. On top of which are Dojo's visual widgets called Dijits. Finally, DojoX contains additional extensions such as charts and a color picker. DojoCampus' Dojo Explorer, http://dojocampus.com/explorer/, has a good selection of single unit demos across the toolkit, many with source code. Dojo allows developers to define widgets using HTML or JavaScript. WaveMaker users will better recognize the JavaScript approach. Specifically, WaveMaker 6.5.X uses version 1.6.1 of Dojo. Of the browsers supported by Dojo 1.6.1, http://dojotoolkit.org/reference-guide/1.8/releasenotes/1.6.html, Opera's "Dojo Core only" support prevents it from being supported by WaveMaker. This could change with Opera's move to WebKit. Building on top of the Dojo Toolkit, WaveMaker provides its own collections of widgets and underlying components. Although both can be called components, the name component is generally used for the non-visible parts, such as service calls to the server and the event notification system. Widgets, such as the Dijits, are visible components such as buttons and editors. Many, but not all, of the WaveMaker widgets extend functionality from Dojo widgets. When they do extend Dijits, WaveMaker widgets often add numerous functions and behaviors that are not part of Dojo. Examples include controlling the read-only state, formatting display values for currency, and merging components, such as buttons with icons in them. Combined with the WaveMaker runtime layers, these enhancements make it easy to assemble rich clients using only properties. WaveMaker's select editor (wm.SelectMenu) for example extends the Dojo Toolkit ComboBox (dijit.form.ComboBox) or the FilteringSelect (dijit.form.FilteringSelect) as needed. By default, a select menu has Dojo FilteringSelect as its editor, but it will use ComboBox instead if the user is on a mobile device or the developer has cleared the RestrictValues property tick box. A required select menu editor Let's consider the case of disabling a submit button when the user has not made a required list selection. In Dojo, this is done using JavaScript code, and for an experienced Dojo developer, this is not difficult. For those who may primarily consider Dojo a martial arts Studio however, it is likely another matter altogether. Using the WaveMaker framework provided widgets, no code is required to set up this inter-connection. This is simply a matter of visually linking or binding the button's disabled property to the lists' emptySelection property in the graphical binding dialog. Now the button will be disabled if the user has not made a selection in the grid's list of items. Logically, we can think of this as setting the disabled property to the value of the grid's emptySelection property, where emptySelection is true unless and until a row has been selected. Where WaveMaker most notably varies from the Dojo way of things is the layout engine. WaveMaker handles the layout of container widgets using its own engine. Containers are those widgets that contain other widgets, such as panels, tabs, and dialogs. This makes it easier for developers to arrange widgets in WaveMaker Studio. A result of this is that border, padding, and margin are set using properties on widgets, not by CSS. Border, padding, and margin are widget properties in WaveMaker, and are not controlled by CSS. Dojo made easy Having the Dojo framework available to us makes web development easier both when using the WaveMaker framework and when doing custom work. Dojo's modular and object-oriented functions, such as dojo.declare and dojo.inherited, for example, simplify creating custom components. The key takeaway here is that Dojo itself is available to you as a developer if you wish to use it directly. Many developers never need to utilize this capability, but it is available to you if you ever do wish to take advantage of it. Running the CRM Simple sample again from either the console in the browser development tools or custom project page code, we could use Dojo's byId() function to get a div, for example, the main title label: >dojo.byId("main_labelTitle"). In practice, the WaveMaker style of getting a DOM node via the component name, for example, main.labelTitle.domNode, is more practical and returns the same result. If a function or ability in Dojo is useful, the WaveMaker framework usually provides a wrapper of some sort for you. Just as often, the WaveMaker version is friendlier or otherwise easier to use in some way. For example, this.connect(), WaveMaker's version of dojo.connect(), tracks connections for you. This avoids the need for you to remember to call disconnect() to remove the reference added by every call to connect(). For more information about using Dojo functions in WaveMaker, see the Dojo framework page in the WaveMaker documentation at: http://dev.wavemaker.com/wiki/bin/wmdoc_6.5/Dojo+Framework. Binding and events Two solid examples of WaveMaker taking a powerful feature of Dojo and providing friendlier versions are topic notifications and event handling. Dojo.connect() enables you to register a method to be called when something happens. In other words: "when X happens, please also do Y". Studio provides visual tooling for this in the events section of a component's properties. Buttons have an event drop-down menu for their click event. Asynchronous server call components, live variables, and service variables, have tooled events for reviewing data just before the call is made and for the successful, and not so successful, returns from the call. These menus are populated with listings of likely components and if appropriate, functions. Invoking other service calls, particularly when a server call depends on data from the results of some previous server call, and navigation calls to other layers and pages within the application are easy examples of how WaveMaker's visual tooling of dojo.connect simplifies web development. WaveMaker's binding dialog is a graphical interface on the topic subscription system. Here we are "binding" a live variable that returns rows from the lineitem table to be filtered by the data value of the orderid editor in the form on the new order page: The result of this binding is that when the value of the orderid editor changes, the value in the filter parameter of this live variable will be updated. An event indicating that the value of this orderid editor has changed is published when the data value changes. This live variable's filter is being subscribed to that topic and can now update its value accordingly. Loading the client Web applications start from index.html, and a WaveMaker application is no different. If we examine index.html of a WaveMaker application, we see the total content is less than 100 lines. We have some meta tags in the head, mostly for Internet Explorer (MSIE) and iOS support. In the body, there are more entries to help out with older versions of MSIE, including script tags to use Chrome Frame if we so choose. If we cut all that away, index.html is rather simple. In the head, we load the CSS containing the projects theme and define a few lines of style classes for wavemakerNode and _wm_loading: <script>var wmThemeUrl = "/wavemaker/lib/wm/base/widget/themes/wm_default/theme.css";</script> <style type="text/css"> #wavemakerNode { height: 100%; overflow: hidden; position: relative; } #_wm_loading { text-align: center; margin: 25% 0px 25% 0px; } </style> Next we load the file config.js, which as its name suggests, is about configuration. The following line of code is used to load the file: <script type="text/javascript" src = "config.js"></script> Config.js defines the various settings, variables, and helper functions needed to initialize the application, such as the locale setting. Moving into the body tag of index.html, we find a div named wavemakerNode: <div id="wavemakerNode"> The next div tag is the loader gif, which is given in the following code: <div id="_wm_loading" style="z-index: 100;"> <table style='width:100%;height: 100%;'><tr><td align='center'><img alt="Loading" src = "/wavemaker/lib/boot/images/loader.gif" />&nbsp;&nbsp;Loading...</td></tr></table> </div> This is the standard spinner shown while the application is loading. With the loader gif now spinning, we begin the real work with runtimeLoader.js, as given in the following line of code: <script type="text/javascript" src = "/wavemaker/lib/runtimeLoader.js"></script> When running a project from Studio, the client runtime is loaded from Studio via WaveMaker. Config.js and index.html are modified for deployment while the client runtime is copied into the applications webapproot. runtimeLoader, as its name suggests, loads the WaveMaker runtime. With the runtime loaded, we can now load the top level project.a.js file, which defines our application using the dojo.declare() method. The following line of code loads the file: <script type="text/javascript" src = "project.a.js"></script> Finally, with our application class defined, we set up an instance of our application in wavemakerNode and run it. There are two modes for loading a WaveMaker application: debug and gzip mode. The debug mode is useful for debugging, as you would expect. The gzip mode is the default mode. The test mode of the Run , Test , or Compile button in Studio re-deploys the active project and opens it in debug mode. This is the only difference between using Test and Run in Studio. The Test button adds ?debug to the URL of the browser window; the Run button does not. Any WaveMaker application can be loaded in debug mode by adding debug to the URL parameters. For example, to load the CRM Simple application from with WaveMaker in debug mode, use the URL http://crm_simple.localhost:8094.com/?debug; detecting debug in the URL sets the djConfig.debugBoot flag, which alters the path used in runtimeLoader. djConfig.debugBoot = location.search.indexOf("debug") >=0; Like a compiled program, debug mode preserves variable names and all the other details that optimization removes which we would want available to use when debugging. However, JavaScript is not compiled into byte code or machine specific instructions. On the other hand, in gzip mode, the browser loads a few optimized packages containing all the source code in merged files. This reduces the number of files needed to load our application, which significantly improves loading time. These optimized packages are also minified. Minification removes whitespace and replaces variable names with short names, further reducing the volume of code to be parsed by the browser, and therefore further improving performance. The result is a significant reduction in the number of requests needed and the number of bytes transferred to load an application. A stock application in gzip mode requires 22 to 24 requests to load some 300 KB to 400 KB of content, depending on the application. In debug mode, the same app transfers over 1.5 MB in more than 500 requests. The index.html file, and when security is enabled, login.html, are yours to edit. If you are comfortable doing so, you can customize these files such as adding additional script tags. In practice, you shouldn't need to customize index.html, as you have full control of the application loaded into the wavemakerNode. Also, upgraded scripts in future versions of WaveMaker may need to programmatically update index.html and login.html. Changes to the X-US-Compatible meta tag are often required when support for newer versions of Internet Explorer becomes available, for example. These scripts can't possibly know about every customization you may make. Customization of index.html may cause these scripts to fail, and may require you to manually update these files. If you do encounter such a situation, simply use the index.html file from a project newly created in the new version as a template. Springing into the server side The WaveMaker server is a Java application running in a Java Virtual Machine (JVM). Like the client, it builds upon proven frameworks and libraries. In the case of the server, the foundational block is the SpringSource framework, http://www.springsource.org/SpringSource, or the Spring framework. The Spring framework is the most popular enterprise Java development framework today, and for good reason. The server of a WaveMaker application is a Spring application that includes the WaveMaker common, json, and runtime modules. More specifically, the WaveMaker server uses the Spring Web MVC framework to create a DispatcherServlet that delegates client requests to their handlers. WaveMaker uses only a handful of controllers, as we will see in the next section. The effective result is that it is the request URL that is used to direct a service call to the correct service. The method value of the request is the name of the client exposed function with the service to be called. In the case of overloaded functions, the signature of the params value is used to find the method matching by signature. We will look at example requests and responses shortly. Behind this controller is not only the power of the Spring framework, but also a number of leading frameworks such as Hibernate and, JaxWS, and libraries such as log4j and Apache commons. Here too, these libraries are available to you both directly in any custom work you might do and indirectly as tooled features of Studio. As we are working with a Spring server, we will be seeing Spring beans often as we examine the server-side configuration. One need not be familiar with Spring to reap its benefits when using custom Java in WaveMaker. Spring makes it easy to get access to other beans from our Java code. For example, if our project has imported a database as MyDB, we could get access to the service and any exposed functions in that service using getServiceBean().The following code illustrates the use of getServiceBean(): MyDB myDbSvc = (MyDB)RuntimeAccess.getInstance().getServiceBean("mydb"); We start by getting an instance of the WaveMaker runtime. From the returned runtime instance, we can use the getServiceBean() method to get a service bean for our mydb database service. There are other ways we could have got access to the service from our Java code; this one is pretty straightforward.  Starting from web.xml Just as the client side starts with index.html, a Java servlet starts in WEB-INF with web.xml. A WaveMaker application web.xml is a rather straightforward Spring MVC web.xml. You'll notice many servlet-mappings, a few listeners, and filters. Unlike index.html, web.xml is managed directly by Studio. If you need to add elements to the web-app context, add them to user-web.xml. The content of user-web.xml is merged into web.xml when generating the deployment package.  The most interesting entry is probably contextConfigLocation of /WEB-INF/project-springapp.xml. Project-springapp.xml is a Spring beans file. Immediately after the schema declaration is a series of resource imports. These imports include the services and entities that we create in Studio as we import databases and otherwise add services to our project. If you open project-spring.xml in WEB-INF, near the top of the file you'll see a comment noting how project-spring.xml is yours to edit. For experienced Spring users, here is the entry point to add any additional imports you may need. An example of such can be found at http://dev.wavemaker.com/wiki/bin/Spring. In that example, an additional XML file, ServerFileProcessor.xml, is used to enable component scanning on a package and sets some properties on those components. Project-spring.xml is then used to import ServerFileProcessor.xml into the application context. Many users of WaveMaker still think of Spring as the season between Winter and Summer. Such users do not need to think about these XML files. However, for those who are experienced with Java, the full power of the Spring framework is accessible to them. Also in project-springapp.xml is a list of URL mappings. These mappings specific request URLs that require handling by the file controller. Gzipped resources, for example, require the header Content-Encoding to be set to gzip. This informs the browser the content is gzip encoded and must be uncompressed before being parsed. >There are a few names that use ag in the server. WaveMaker Software the company was formerly known as ActiveGrid, and had a previous web development tool by the same name. The use of ag and com.activegrid stems back to the project's roots, first put down when the company was still known as ActiveGrid. Closing out web.xml is the Acegi filter mapping. Acegi is the security module used in WaveMaker 6.5 . Even when security is not enabled in an application, the Acegi filter mapping is included in web.xml. When security is not enabled in the project, an empty project-security.xml is used. Client and server communication Now that we've examined the client and server, we need to better understand the communication between the two. WaveMaker almost exclusively uses the HTTP methods GET and POST. In HTTP, GET is used, as you might suspect even without ever having heard of RFC 2626 (https://tools.ietf.org/html/rfc2616), to request, or get, a specific resource. Unless installed as a native application on a mobile device, a WaveMaker web application is loaded via a GET method. From index.html and runtimeLoad.js to the user defined pages and any images used on those images, the applications themselves are loaded into the browser using GET. All service calls, database reads and writes, or otherwise any invocations of a Java service functions, on the other hand, are POST. The URL of these POST functions is always the service named .json. For example, calls to a Java service named userPrefSvc would always be to the URL /userPrefSvc.json. Inside the POST method's request payload will be any required parameters including the method of the service to be invoked. The response will be the response returned from that call. PUT methods are not possible because we cannot nor do not want to know all possible WaveMaker server calls at "designtime", while the project files are open for writing in the Studio. This pattern avoids any URL length constraints, enabling lengthy datasets to be transferred while freeing up the URL to pass parameters such as page state. Let's take a look at an example. If you want to follow along in your browser's console, this is the third request of three when we select "Fog City Books" in the CRM Simple application when running the application with the console open. The following URL is the request URL: http://crm_simple.localhost:8094/services/runtimeService.json The following is request payload: {"params":["custpurchaseDB","com.custpurchasedb.data.Lineitem",null,{"properties":["id","item"],"filters":["id.orderid=9"],"matchMode":"start","ignoreCase":false},{"maxResults":500,"firstResult":0}],"method":"read","id":251422} The response is as follows: {"dataSetSize":2,"result":[{"id":{"itemid":2,"orderid":9},"item":{"itemid":2,"itemname":"Kidnapped","price":12.99},"quantity":2},{"id":{"itemid":10,"orderid":9},"item":{"itemid":10,"itemname":"Gravitys Rainbow","price":11.99},"quantity":1}]} As we expect, the request URL is to a service (in this case named runtime service), with the .json extension. Runtime service is the built-in WaveMaker service for reading and writing with the Hibernate (http://www.hibernate.org), data models generated by importing a database. Security service and WaveMaker service are the other built-in services used at runtime. The security service is used for security functions such as getUserName() and logout(). Note this does not include login, which is handled by Acegi. The WaveMaker service has functions such as getServerTimeOffset(), used to adjust for time zones, and remoteRESTCall(), used to proxy some web service calls. How the runtime service functions is easy to understand by observation. Inside the request payload we have, as the URL suggested, a JavaScript Object Notation (JSON) structure. JSON (http://www.json.org/), is a lightweight data-interchange format regularly used in AJAX applications. Dissecting our example request from the top of the structure enclosed in the outer-most {}'s looks like the following: {"params":[…….],"method":"read","id":251422} We have three top level name-value pairs to our request object: params, method, and id. The id is 251422; method is read and the params value is an array, as indicated by the [] brackets: ["custpurchaseDB","com.custpurchasedb.data.Lineitem",null,{},{ }] In our case, we have an array of five values. The first is the database service name, custpurchaseDB. Next we have what appears to be the package and class name we will be reading from, not unlike from in a SQL query. After which, we have a null and two objects. JSON is friendly to human reading, and we could continue to unwrap the two objects in this request in a similar fashion.  when we discuss database services and check out the response. At the top level, we have dataSetSize, the number of results, and the array of the results: {"dataSetSize":2,"result":[]} Inside our result array we have two objects: [{"id":{"itemid":2,"orderid":9},"item":{"itemid":2,"itemname":"Kidnapped","price":12.99},"quantity":2},{"id":{"itemid":10,"orderid":9},"item":{"itemid":10,"itemname":"Gravitys Rainbow","price":11.99},"quantity":1}]} Our first item has the compound key of itemid 2 with orderid 9. This is the item Kidnapped, which is a book costing $11.99. The other object in our result array also has the orderid 9, as we expect when reading line items from the selected order. This one is also a book, the item Gravity's Rainbow. Types To be more precise about the com.custpurchasdb.data.Lineitem parameter in our read request, it is actually the type name of the read request. WaveMaker projects define types from primitive types such as Boolean and custom complex types such as Lineitem. In our runtime read example, com.custpurchasedb.data.Lineitem is both the package and class name of the imported Hibernate entity and the type name for the line item entity in the project. Maintaining type information enables WaveMaker to ease a number of development issues. As the client knows the structure of the data it is getting from the server, it knows how to display that data with minimal developer configuration, if any. At design time, Studio uses type information in many areas to help us correctly configure our application. For example, when we set up a grid, type information enables Studio to present us with a list of possible column choices for the grid's dataset type. Likewise, when we add a form to the canvas for a database insert, it is type information that Studio uses to fill the form with appropriate editors. Line item is a project-wide type as it is defined in the server side. In the process of compiling the project's Java services sources, WaveMaker defines system types for any type returned to the client in a client facing function. To be added to the type system, a class must: Be public Define public getters and setters Be returned by a client exposed function Have a service class that extends JavaServiceSuperClass or uses the @ExposeToClient annotation WaveMaker 6.5.1 has a bug that prevents types from being generated as expected. Be certain to use 6.5.2 or newer versions to avoid this defect. It is possible to create new project types by adding a Java service class to the project that only defines types. Following is an example that creates a new simple type called Record to the project. Our definition of Record consists of an integer ID and a string. Note that there are two classes here. MyCustomTypes is the service class containing a method returning the type Record. As we will not be calling it, the function getNewRecord() need not do anything other than return a record. Creating a new default instance is an easy way to do this. The class Record is defined as an inner class. An inner class is a class defined within another class. In our case, Record is defined within MyCustomTypes: // Java Service class MyCustomTypes package com.myco.types; import com.wavemaker.runtime.javaservice.JavaServiceSuperClass; import com.wavemaker.runtime.service.annotations.ExposeToClient; public class MyCustomTypes extends JavaServiceSuperClass { public Record getNewRecord(){ return new Record(); } // Inner class Record public class Record{ private int id; private String name; public int getId(){ return id; } public void setId(int id){ this.id = id; } public String getName(){ return this.name; } public void setName(String name){ this.name = name; } } }  To add the preceding code to our WaveMaker project, we would add a Java service to the project using the class name MyCustomTypes in the Package and Class Name editor of the New Java Service dialog. The preceding code extends JavaServiceSuperClass and uses the package com.myco.types. A project can also have client-only types using the type definition option from the advanced section of the Studio insert menu. Type definitions are useful when we want to be able to pass structured data around within the client but we will not be sending or receiving that type to the server. For example, we may want to have application scoped wm.Variable storing a collection of current record selection information. This would enable us to keep track of a number of state items across all pages. Communication with the server is likely to be using only a few of those types at a time, so no such structure exists in the server side. Using wm.Variable enables us to bind each Record ID without using code. The insert type definition menu brings up the Type Definition Generator dialog. The generator takes JSON input and is pre-populated with a sample type. The sample type defines a person object, albeit an unusual one, with a name, an array of numbers for age, a Boolean (hasFoot), and a related person object, friend. Replace the sample type with your own JSON structure. Be certain to change the type name to something meaningful. After generating the type, you'll immediately see the newly minted type in type selectors, such as the type field of wm.Variable. Studio is pretty good at recognizing type changes. If for some reason Studio does not recognize a type change, the easiest thing to do is to get Studio to re-read the owning object. If a wm.Variable fails to show a newly added field to a type in its properties, change the type of the variable from the modified type to some other type and then back again. Studio is also an application One of the more complex WaveMaker applications is the Studio. That's right, Studio is itself an application built out of WaveMaker widgets and using the runtime and server. Being the large, complex application we use to build applications, it can sometimes be difficult to understand where the runtime ends and Studio begins. With that said, Studio remains a treasure trove of examples and ideas to explore. Let's open a finder, explorer, shell, or however you prefer to view the file system of a WaveMaker Studio installation. Let's look in the studio folder. If you've installed WaveMaker to c:program filesWaveMaker6.5.3.Release, the default on Windows, we're looking at c:program filesWaveMaker6.5.3.Releasestudio. This is the webapproot of the Studio project: For files, we've discussed index.html in loading the client. The type definition for the project types is types.js. The types.js definition is how the client learns of the server's Java types. Moving on to the directories alphabetically, we start with the app folder. The app folder can be considered a large utility folder these days. The branding folder, http://dev.wavemaker.com/wiki/bin/wmdoc_6.5/Branding, is a sample of the branding feature for when you want to easily re-brand applications for different customers. The build folder contains the optimized build files we discussed when loading our application in gzip mode. This build folder is for the Studio itself. The images folder is, as we would hope, where images are kept. The content of the doc in jsdoc is pretty old. Use jsref at the online wiki, http://dev.wavemaker.com/wiki/bin/wmjsref_6.5/WebHome, for a client API reference instead. Language contains the National Language Support (NLS) files to localize Studio into other languages. In 6.5.X, there is a Japanese (ja) and Spanish (es) directory in addition to the English (en) default thanks to the efforts of the WaveMaker community and a corporate partner. For more on internationalization applications with WaveMaker, navigate to http://dev.wavemaker.com/wiki/bin/wmdoc_6.5/Localization#HLocalizingtheClientLanguage. The lib folder is very interesting, so let's wrap up this top level before we dig into that one. The META-INF folder contains artifacts from the WaveMaker Maven build process that probably should be removed for 6.5.2. The pages folder contains the page definitions for Studio's pages. These pages can be opened in Studio. They also can be a treasure trove of tips and tricks if you see something when using Studio that you don't know how to do in your application. Be careful however, as some pages are old and use outdated classes or techniques. Other constructs are only used by Studio and aren't tooled. This means some pages use components that can only be created by code. The other major difference between a project's pages folder is that Studio page folders do not contain the same number of files. They do not have the optimized pageName.a.js file, for example. The services folder contains the Service Method Definition (SMD) files for Studio's services. These are summaries of a projects exposed services, one file per service, used at runtime by the client. Each callable function, its input parameter, and its return types are defined. Finally, WEB-INF we have discussed already when we examined web.xml. In Studio's case, replace project with studio in the file names. Also under WEB-INF, we have classes and lib. The classes folder contains Java class files and additional XML files. These files are on the classpath. WEB-INFlib contains JAR files. Studio requires significantly more JAR files, which are automatically added to projects created by Studio. Now let's get back to the lib folder. Astute readers of our walk through of index.html likely noticed the references to /wavemaker/lib in src tags for things such as runtimeloader. You might have also noticed that this folder was not present in the project and wondered how these tags could not fail. As a quick look at the URL of Studio running in a browser will demonstrate, /wavemaker is the Studio's context. This means the JavaScript runtime is only copied in as part of generating the deployment package. The lib folder is loaded directly from Studio's context when you test run an application from Studio using the Run or Test button. RuntimeLoader.js we encountered following index.html as it is the start of the loading of client modules. Manifest.js is an entry point into the loading process. Boot contains pre-initialization, such as the spinning loader image. Next we have another build folder. This one is the one used by applications and contains all possible build files. Not every JavaScript module is packaged up into an optimized build file. Some modules are so specific or rarely used that they are best loaded individually. Otherwise, if there's a build package available to applications, these them. Dojo lives in the dojo folder. I hope you don't find it surprising to find a dijit, dojo, and dojox folder in there. The folder github provides the library path github for JS Beautifier, http://jsbeautifier.org/. The images in the project images folder include a copy of Silk Icons, http://www.famfamfam.com/lab/icons/silk/, a great Creative Common licensed PNG icon set. This brings us to wm. We definitely saved the most interesting folder for our last stop on this tour. For in lib/wm, we have manifest.js, the top level of module loading when using debug mode in the runtime loader. In wm/lib/base, is the top level of the WaveMaker module space used at runtime. This means in wm/lib/base we have the WaveMaker components and widgets folders. These two folders contain the most commonly used sets of classes by WaveMaker developers using any custom JavaScript in a project. This also means we will be back in these folders again too. Summary In this article, we reviewed the WaveMaker architecture. We started with some context of what we mean by "client" and "server" in the context of this book. We then proceeded to dig into the client and the server. We reviewed how both build upon leading frameworks, the Dojo Toolkit and the SpringSource Framework in particular. We examined the running of an application from the network point of view and how the client and server communicated throughout. We dissected a JSON request to the runtime service and encountered project types. We also learned about both project and client type definitions. We ended by revisiting the file system. This time, however, we walked through a Studio installation. Studio is also a WaveMaker application. In the next article, we'll get comfortable with the Studio as a visual tool. We'll look at everything from the properties panels to the built-in source code editors. Resources for Article : Further resources on this subject: Binding Web Services in ESB—Web Services Gateway [Article] Service Oriented JBI: Invoking External Web Services from ServiceMix [Article] Web Services in Apache OFBiz [Article]
Read more
  • 0
  • 0
  • 2274

article-image-accessing-and-using-rdf-data-stanbol
Packt
30 Jul 2013
6 min read
Save for later

Accessing and using the RDF data in Stanbol

Packt
30 Jul 2013
6 min read
(For more resources related to this topic, see here.) Getting ready To start with, we need a Stanbol instance and Node.js. Additionally, we need the file rdfstore-js, which can be installed by executing the following command line: > npm install rdfstore How to do it... We create a file rdf-client.js with the following code: var rdfstore = require('rdfstore'); var request = require('request'); var fs = require('fs'); rdfstore.create(function(store) { function load(files, callback) { var filesToLoad = files.length; for (var i = 0; i < files.length; i++) { var file = files[i] fs.createReadStream(file).pipe( request.post( { url: 'http://localhost:8080/enhancer?uri=file: ///' + file, headers: {accept: "text/turtle"} }, function(error, response, body) { if (!error && response.statusCode == 200) { store.load( "text/turtle", body, function(success, results) { console.log('loaded: ' + results + " triples from file" + file); if (--filesToLoad === 0) { callback() } } ); } else { console.log('Got status code: ' + response.statusCode); } })); } } load(['testdata.txt', 'testdata2.txt'], function() { store.execute( "PREFIX enhancer:<http://fise.iks-project. eu/ontology/> PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#> SELECT ?label ?source { ?a enhancer:extracted-from ?source. ?a enhancer:entity-reference ?e. ?e rdfs:label ?label. FILTER (lang(?label) = "en") }", function(success, results) { if (success) { console.log("*******************"); for (var i = 0; i < results.length; i++) { console.log(results[i].label.value + " in " + results[i].source.value); } } }); }); }); Create the data files:Our client loads two files. We use a simple testdata.txt file having the content: "The Stanbol enhancer can detect famous cities such as Paris and people such as Bob Marley." And a second testdata2.txt file with the following content: "Bob Marley never had a concert in Vatican City." We execute the code using Node.js command line: > node rdf-client.js The output is: loaded: 159 triples from file testdata2.txt loaded: 140 triples from file testdata2.txt ******************* Vatican City in file:///testdata2.txt Bob Marley in file:///testdata2.txt Bob Marley in file:///testdata.txt Paris, Texas in file:///testdata.txt Paris in file:///testdata.txt This time we see the labels of the entities and the file in which they appear. How it works… Unlike the usual clients, this client no longer analyses the returned JavaScript Object Notation (JSON) but processes the returned data as RDF. An RDF document is a directed graph. The following screenshot shows some RDF rendered as graph by the W3C We can create such an image by selecting RDF/XML as the output format on localhost:8080/enhancer , copying and pasting the XML generated, and running the engines on some text to www.w3.org/RDF/Validator/ , where we can request that triples and graphs be generated from it. Triples are the other way to look at RDF. An RDF graph (or document) is a set of triples of the form– subject-predicate-object, where subject and object are the nodes (vertices) and predicate is the arc (edge). Every triple is a statement describing a property of its subject: <urn:enhancement-f488d7ce-a1b7-faa6-0582-0826854eab5e> <http://fise. iks-project.eu/ontology/entity-reference> <http://dbpedia.org/resource/ Bob_Marley>. <http://dbpedia.org/resource/Bob_Marley> <http://www.w3.org/2000/01/rdf-schema#label> "Bob Marley"@en . There are two triples saying that an enhancement referenced Bob Marley and that the English label for Bob Marley is "Bob Marley". All the arches and most of the nodes are labeled by an Internationalized Resource Identifier (IRI), which defines a superset of the good old URLs including non-Latin characters. RDF can be serialized in many different formats. The two triples in the preceding command lines use the N-TRIPLES syntax. RDF/XML expresses (serializes) RDF graphs as XML documents. Originally, RDF/XML was referred to as the canonical serialization for RDF. Unfortunately, this caused some people to believe RDF would be somehow related to XML and thus inherit its flaws. A serialization format designed specifically for RDF that doesn't encode RDF into an existing format is Turtle. Turtle allows both explicit listing of triples as in N-TRIPLES but also supports various ways of expressing the graphs in a more concise and readable fashion. The JSON-LD, expresses RDF graphs in JSON. As this specification is currently still work in progress (see json-ld.org/), different implementations are incompatible and thus, for this example, we switched the Accept-Header to text/turtle. Another change in the code performing the request is that we added a uri query-parameter to the requested URL: 'http://localhost:8080/enhancer?uri=file:///' + file,   This defines the IRI naming used as a name for the uploaded content in the result graph. If this parameter is not specified, the enhancer will generate an IRI which is based on creating a hash of the content. But this line in the output would be less helpful: Paris in urn:content-item-sha1-3b16820497aae806f289419d541c770bbf87a796 Roughly the first half of our code takes care of sending the files to Stanbol and storing the returned RDF. We define a function load that asynchronously enhances a bunch of files and invokes a callback function when all files have successfully been loaded. The second half of the code is the function that's executed once all files have been processed. At this point, we have all the triples loaded in the store. We could now programmatically access the triples one by one, but it's easier to just query for the data we're interested in. SPARQL is a query language a bit similar to SQL but designed to query triple stores rather than relational databases. In our program, we have the following query (slightly simplified here): PREFIX enhancer:<http://fise.iks-project.eu/ontology/> PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#> SELECT ?label ?source { ?a enhancer:extracted-from ?source. ?a enhancer:entity-reference ?e. ?e rdfs:label ?label. } The most important part is the section between curly brackets. This is a graph pattern that is like a graph, but with some variables instead of values. On execution, the SPARQL engine will check for parts of the RDF matching this pattern and return a table with a row for each selected value and a row for every matching value combination. In our case, we iterate through the result and output the label of the entity and the document in which the entity was referenced. There's more... The advantage of RDF is that many tools can deal with the data, ranging from command line tools such as rapper (librdf.org/raptor/rapper.html) for converting data to server applications, which allow to store large amounts of RDF data and build applications on top of it. Summary In this recipe, the advantage of using RDF (model-based) over the conventional JSON (syntax-based)method is explained. In the article, a client was created, rdf-client.js, which loaded two files, testdata.txt and testdata2.txt, and then were executed using Node.js command prompt. An RDF was rendered using W3C in the form of triples. Later, using SPARQL the triples were queried to extract the required information. Resources for Article : Further resources on this subject: Installing and customizing Redmine [Article] Web Services in Apache OFBiz [Article] Geronimo Architecture: Part 2 [Article]
Read more
  • 0
  • 1
  • 2319
article-image-coding-real-time-web
Packt
30 Jul 2013
9 min read
Save for later

Coding for the Real-time Web

Packt
30 Jul 2013
9 min read
(For more resources related to this topic, see here.) As the lines between web apps and traditional desktop apps blur, our users have come to expect real-time behavior in our web apps—something that is traditionally the domain of the desktop. One cannot really blame them. Real-time interaction with data, services, and even other users has driven the connected revolution, and we are now connected in more ways than ever before. However valid this desire to be always connected and immediately informed of an event, there are inherent challenges in real-time interactions within web apps. The first challenge is that the Web is stateless. The Web is built on HTTP, a protocol that is request/response; for each request a browser makes, there is one and only one response. There are frameworks and techniques we can use to mask the statelessness of the Web, but there is no true state built into the Web or HTTP. This is further complicated as the Web is client/server. As it's stateless, a server only knows of the clients connected at any one given moment, and clients can only display data to the user based upon the last interaction with the server. The only time the client and server have any knowledge of the other is during an active request/response, and this action may change the state of the client or the server. Any change to the server's state is not reflected to the other clients until they connect to the server with a new request. It's somewhat like the uncertainty principle in that the more one tries to pin down one data point of the relationship, the more uncertain one becomes about the other points. All hope is not lost. There are several techniques that can be used to enable real-time (or near real-time) data exchange between the web server and any active client. Simulating a connected state In traditional web development, there has not been a way to maintain a persistent connection between a client browser and the web server. Web developers have gone to great lengths to try and simulate a connected world in the request/response world of HTTP. Several developers have met with success using creative thinking and loopholes within the standard itself to develop techniques such as long polling and the forever frame. Now, thanks to the realization that such a technique is needed, the organizations overseeing the next generation of web standards are also heeding the call with server-sent events and web sockets. Long polling Long polling is the default fallback for any client and server content exchange. It is not reliant on anything but HTTP—no special standards checklists or other chicanery are required. Long polling is like getting the silent treatment from your partner. You ask a question and you wait indefinitely for an answer. After some known period of time and what may seem like an eternity, you finally receive an answer or the request eventually times out. The process repeats again and again until the request is fully satisfied or the relationship terminates. So, yeah, it's exactly like the silent treatment. Forever Frame The Forever Frame technique relies on the HTTP 1.1 standard and a hidden iframe. When the page loads, it contains (or constructs) a hidden iframe used to make a request back to the server. The actual exchange between the client and the server leverages a feature of HTTP 1.1 known as Chunked Encoding. Chunked Encoding is identified by a value of chunked in the HTTP Transfer-Encoding header. This method of data transfer is intended to allow the server to begin sending portions of data to the client before the entire length of the content is known. When simulating a real-time connection between a browser and web server, the server can dispatch messages to the client as individual chunks on the request made by the iframe. Server-Sent Events Server-Sent Events (SSE) provide a mechanism for a server to raise DOM events within a client web browser. This means to use SSE, the browser must support it. As of this writing, support for SSE is minimal but it has been submitted to W3C for inclusion into the HTML5 specification. The use of SSE begins by declaring an EventSource variable: var source = new EventSource('/my-data-source'); If you then want to listen to any and all messages sent by the source, you simply treat it as a DOM event and handle it in JavaScript. source.onmessage = function(event) {// Process the event.} SSE supports the raising of specific events and complex event messaging. The message format is a simple text-based format derivative of JSON. Two newline characters separate each message within the stream, and each message may have an id, data, and event property. SSE also supports setting the retry time using the retry keyword within a message. :comment:simple messagedata:"this string is my message":complex message targeting an eventevent:thatjusthappeneddata:{ "who":"Professor Plum", "where":"Library", "with":"candlestick"} As of this writing, SSE is not supported in Internet Explorer and is partially implemented in a few mobile browsers. WebSockets The coup de grâce of real-time communication on the Web is WebSockets. WebSockets support a bidirectional stream between a web browser and web server and only leverage HTTP 1.1 to request a connection upgrade. Once a connection upgrade has been granted, WebSockets communicate in full-duplex using the WebSocket protocol over a TCP connection, literally creating a client-server connection within the browser that can be used for real-time messaging. All major desktop browsers and almost all mobile browsers support WebSockets. However, WebSocket usage requires support from the web server, and a WebSocket connection may have trouble working successfully behind a proxy. With all the tools and techniques available to enable real-time connections between our mobile web app and the web server, how does one make the choice? We could write our code to support long polling, but that would obviously use up resources on the server and require us to do some pretty extensive plumbing on our end. We could try and use WebSockets, but for browsers lacking support or for users behind proxies, we might be introducing more problems than we would solve. If only there was a framework to handle all of this for us, try the best option available and degrade to the almost guaranteed functionality of long polling when required. Wait. There is. It's called SignalR. SignalR provides a framework that abstracts all the previously mentioned real-time connection options into one cohesive communication platform supporting both web development and traditional desktop development. When establishing a connection between the client and server, SignalR will negotiate the best connection technique/technology possible based upon client and server capability. The actual transport used is hidden beneath a higher-level communication framework that exposes endpoints on the server and allows those endpoints to be invoked by the client. Clients, in turn, may register with the server and have messages pushed to them. Each client is uniquely identified to the server via a connection ID. This connection ID can be used to send messages explicitly to a client or away from a client. In addition, SignalR supports the concept of groups, each group being a collection of connection IDs. These groups, just like individual connections, can be specifically included or excluded from a communication exchange. All of these capabilities in SignalR are provided to us by two client/server communication mechanisms: persistent connections and hubs Persistent connections Persistent connections are the low-level connections of SignalR. That's not to say they provide access to the actual communication technique being used by SignalR, but to illustrate their primary usage as raw communication between client and server. Persistent connections behave much as sockets do in traditional network application development. They provide an abstraction above the lower-level communication mechanisms and protocols, but offer little more than that. When creating an endpoint to handle persistent connection requests over HTTP, the class for handling the connection requests must reside within the Controllers folder (or any other folder containing controllers) and extend the PersistentConnection class. public class MyPersistentConnection: PersistentConnection{} The PersistentConnection class manages connections from the client to the server by way of events. To handle these connection events, any class that is derived from PersistentConnection may override the methods defined within the PersistentConnection class. Client interactions with the server raise the following events: OnConnected: This is invoked by the framework when a new connection to the server is made. OnReconnected: This is invoked when a client connection that has been terminated has reestablished a connection to the server. OnRejoiningGroups: This is invoked when a client connection that has timed out is being reestablished so that the connection may be rejoined to the appropriate groups. OnReceived: This method is invoked when data is received from the client OnDisconnected: This is invoked when the connection between the client and server has been terminated. Interaction with the client occurs through the Connection property of the PersistentConnection class. When an event is raised, the implementing class can determine if it wishes to broadcast a message using Connection.Broadcast, respond to a specific client using Connection.Send, or add the client that triggered the message to a group using Connection.Groups. Hubs Hubs provide us an abstraction over the PersistentConnection class by masking some of the overhead involved in managing raw connections between client and server. Similar to a persistent connection, a hub is contained within the Controllers folder of your project but instead, extends the Hub base class. public class MyHub : Hub{} While a hub supports the ability to be notified of connection, reconnection, and disconnection events, unlike the event-driven persistent connection a hub handles the event dispatching for us. Any publicly available method on the Hub class is treated as an endpoint and is addressable by any client by name. public class MyHub : Hub{public void SendMeAMessage(string message){ /* ... */ }} A hub can communicate with any of its clients using the Clients property of the Hub base class. This property supports methods, just like the Connection property of PersistentConnection, to communicate with specific clients, all clients, or groups of clients. Rather than break down all the functionality available to us in the Hub class, we will instead learn from an example.
Read more
  • 0
  • 0
  • 4111

article-image-tasks-and-templates
Packt
29 Jul 2013
13 min read
Save for later

Tasks and templates

Packt
29 Jul 2013
13 min read
(For more resources related to this topic, see here.) Running commands with exec resources We've seen that Puppet lets you model various aspects of a system using resources, such as user or file resources. You describe how the system should be configured, and Puppet will run appropriate commands behind the scenes to bring about the desired state. But what if you want Puppet to run a certain command directly? You can do this using an exec resource. This is a very flexible and powerful resource, and you can use it to implement almost anything in Puppet. In this section we'll see how to get the most from exec resources. Time for action – running an arbitrary command Modify your manifests/nodes.pp file as follows: node 'demo' { exec { 'Run my arbitrary command': command => '/bin/echo I ran this command on `/bin/date` >/tmp/command.output.txt', }} Run Puppet: ubuntu@demo:~/puppet$ papplyNotice: /Stage[main]//Node[demo]/Exec[Run my arbitrary command]/returns: executed successfullyNotice: Finished catalog run in 0.14 seconds Check the output produced (you won't see exactly the same date and time shown here, unless you're a Time Lord): ubuntu@demo:~/puppet$ cat /tmp/command.output.txt I ran this command on Mon Dec 17 16:14:04 UTC 2012 What just happened? The line exec { 'Run my arbitrary command': declares an exec resource with the name Run my arbitrary command. The name can be anything; it's not otherwise used by Puppet, except that like all resource names it can't be the same as another instance of the same resource type. The command to run is specified by the following line: command => '/bin/echo I ran this command on `/bin/date` >/tmp/command.output.txt', Note that the UNIX commands, echo and date, are specified with their full path. This is because Puppet wants to be sure exactly which command you mean. When Puppet runs, it applies the exec resource by running the command: /bin/echo I ran this command on `/bin/date` >/tmp/command.output.txt This command will write the following text to /tmp/command.output.txt: I ran this command on Mon Dec 17 16:14:04 UTC 2012 Running commands selectively The exec resource we've created will be applied every time Puppet runs, but that's not always what we want. Say we are using an exec resource to download a file, for example. Once the file is downloaded the first time we don't need to do it again. Here's an example: exec { 'Download public key for John': cwd => '/tmp', command => '/usr/bin/wget http: // bitfieldconsulting.com/files/john.pub', creates => '/tmp/john.pub',} The creates attribute specifies the full path to a file. Puppet will check to see if this file already exists. If it does, the exec won't be run. This is a neat way to have a command run only if it is needed, and not otherwise. Did you notice we also added the cwd attribute? This tells Puppet the directory in which to run the command (cwd stands for current working directory), so that any files created by the command, like john.pub in this example, will end up in that directory. You can also use the unless or onlyif attributes to control when an exec is run. unless or onlyif both specify a command for Puppet to run to test whether the exec needs to be applied. The exit status of the test command determines what Puppet should do. For example: exec { 'add-cloudera-apt-key': command => '/usr/bin/apt-key add /tmp/cloudera.pub', unless => '/usr/bin/apt-key list |grep Cloudera',} Here, we're using an exec to add an APT repository key to the system keyring. This only needs to be done once, so the unless command checks whether the key has already been added. If the grep succeeds, we know the key is already present, so we don't need to do anything. The exit status will be zero, so Puppet won't apply the exec. On the other hand, if the grep fails, the exit status will be non-zero so Puppet will apply the exec. Using onlyif, the opposite logic applies; the exec will be run only if the test command succeeds (exits with a zero status). Triggering commands Another way to control when an exec is run is to use the refreshonly attribute: exec { 'icinga-config-check': command => '/usr/sbin/icinga -v /etc/icinga/icinga.cfg && /usr/sbin/service icinga restart', refreshonly => true, subscribe => File['/etc/icinga/icinga.cfg'],} When refreshonly is set, Puppet will not apply the exec unless it's triggered by subscribe or notify from some other resource. In this example, the exec subscribes to the file /etc/icinga/icinga.cfg. If this file changes, Puppet will run the exec, but not otherwise. This is a very useful pattern when you want to take some action if a config file changes,especially if you want to sanity-check the file's contents (as in the example) before restarting the service that reads it. Chaining commands Often you have a series of commands that need to run in a particular order (for example, if you're installing sofware from source, you might need to download a file, unpack it, build it, and install it). To do this, for short sequences, you can use the shell && construct as shown in the preceding example: /usr/sbin/icinga -v /etc/icinga/icinga.cfg && /usr/sbin/service icinga restart This will chain the commands together in the order you specify, bailing out if any of the commands fail. For more complicated sequences, or where you may also need to trigger individual commands from other resources, you can use the require attribute to specify the ordering explicitly: exec { 'command-1': command => '/bin/echo Step 1',}exec { 'command-2': command => '/bin/echo Step 2', require => Exec['command-1'],}exec { 'command-3': command => '/bin/echo Step 3', require => Exec['command-2'],} Command search paths As we've seen, Puppet requires us to specify the full path to any command referenced in an exec resource. However, if you like, you can provide a list of paths for Puppet to search for commands, using the path attribute. For example: exec { 'Run my arbitrary command': command => 'echo I ran this command on `date` >/tmp/command.output.txt', path => ['/bin', '/usr/bin'],} Now when Puppet sees a command name, it will search the directories you specify looking for the matching commands. If you want to specify a set of default search paths for all exec resources, you can put this in your site.pp file: Exec { path => ['/bin', '/usr/bin'],} Note the capital E for Exec. This means "make this the default for all exec resources." Then you can use unqualified commands without an explicit path attribute: exec { 'Run my arbitrary command': command => 'echo I ran this command on `date` >/tmp/command.output.txt',} Puppet will use the default paths you specified: /bin and /usr/bin. Scheduled tasks Typically, when you want a command to be run at a certain time of day, or at regular intervals, you can use the UNIX cron facility. For example, a backup job might run every night at 4 a.m., or a queue processing task might run every 5 minutes. Puppet can manage cron jobs directly using the cron resource type. Here's an example. Time for action – scheduling a backup Modify your manifests/nodes.pp file as follows: node 'demo' { cron { 'Back up cat-pictures': command => '/usr/bin/rsync -az /var/www/cat-pictures/ /cat-pictures-backup/', hour => '04', minute => '00', }} Run Puppet: ubuntu@demo:~/puppet$ papplyNotice: /Stage[main]//Node[demo]/Cron[Back up cat-pictures]/ensure: createdNotice: Finished catalog run in 0.12 seconds Check that the cron job was correctly configured: ubuntu@demo:~/puppet$ sudo crontab -l# HEADER: This file was autogenerated on Tue Dec 18 12:50:11 +0000 2012 by puppet.# HEADER: While it can still be managed manually, it is definitely not recommended.# HEADER: Note particularly that the comments starting with 'Puppet Name' should# HEADER: not be deleted, as doing so could cause duplicate cron jobs.# Puppet Name: Back up cat-pictures0 4 * * * /usr/bin/rsync -avz /var/www/cat-pictures/ /cat-pictures-backup/ What just happened? The line cron { 'Back up cat-pictures': declares a cron resource named Back up cat-pictures (as with exec resources, the name doesn't mater, but it must be unique). command => '/usr/bin/rsync -avz /var/www/cat-pictures/ /cat-pictures-backup/', The preceding line sets the command to run (in this case, an rsync command to back up all files and directories under /var/www/cat-pictures to /cat-pictures-backup). As with exec resources, commands need to be qualified with their full path. We now go on to specify the time at which the job should run. hour => '04', This is in 24-hour format, with 00 being midnight, and 23 being 11 p.m. minute => '00', If minute is not specified, it defaults to *; that is, it runs every minute! So always specify both hour and minute (if there is no hour, the job runs every hour at the minute you specify). Note that Puppet adds a helpful header to the crontab file, warning you not to meddle in the affairs of Puppet. In fact, you can safely add, remove, and modify any cron jobs not managed by Puppet. Puppet identifies the cron jobs it's managing by the Puppet Name comment above each job. So, as the warning suggests, don't remove or edit these comments or Puppet will think the job is missing and add a new copy of it. More scheduling options The cron resources can have several other attributes to set the time for the scheduled job: weekday – the day of the week, for example, Friday month – not often used, but can be used to run jobs only during a specific month, for example, January monthday – the day of the month, for example 1 to run a job on the first day of each month If any of these attributes are not supplied, they default to *; that is, every weekday, every month, or every day of the month. Running jobs at regular intervals If you want to run a job every 5 minutes, say, you can specify an interval such as this: minute => '*/5',hour => '*', You can use the same pattern with the other time attributes, for example, to run a job every 6 hours on the hour: hour => '*/6',minute => '00', Running a job as a specified user The default user for cron jobs is root, but if you want to run the job as a different user,just give the cron resource a user attribute: user => 'www-data', The job will be added to the crontab file for www-data. Exercise Use a cron resource to automate the pull-updates job you set up in Managing Puppet with Git, which automatically pulls Git changes and applies Puppet on each machine. Make this part of every machine's base configuration. Distributing files Sometimes, though, you need to copy a whole directory tree of files, without having to list each individual file in your Puppet manifest. The recurse attribute allows you to do this. We'll see how to use it in the next example. Time for action – using a recursive file resource The cat-pictures application is nearly complete, but it needs some pictures of cats added in time for the launch. The art department has sent over a set of feline stock photos for you to deploy to the website. Create the directories for a new cat-pictures module: ubuntu@demo:~/puppet$ mkdir modules/cat-picturesubuntu@demo:~/puppet$ mkdir modules/cat-pictures/files Create a directory for the images, and some placeholder image files (for extra credit, download some real pictures of cats from the Internet): ubuntu@demo:~/puppet$ mkdir modules/cat-pictures/files/imgubuntu@demo:~/puppet$ mkdir modules/cat-pictures/files/img/cat_001.jpgubuntu@demo:~/puppet$ mkdir modules/cat-pictures/files/img/cat_002.jpgubuntu@demo:~/puppet$ mkdir modules/cat-pictures/files/img/cat_003.jpg Modify your manifests/nodes.pp file as follows: node 'demo' { file { '/var/www/cat-pictures': ensure => directory, } file { '/var/www/cat-pictures/img': source => 'puppet:///modules/cat-pictures/img', recurse => true, require => File['/var/www/cat-pictures'], }} Run Puppet: ubuntu@demo:~/puppet$ papplyNotice: /Stage[main]//Node[demo]/File[/var/www/cat-pictures]/ensure: createdNotice: /Stage[main]//Node[demo]/File[/var/www/cat-pictures/img]/ensure: createdNotice: /File[/var/www/cat-pictures/img/cat_002.jpg]/ensure: createdNotice: /File[/var/www/cat-pictures/img/cat_001.jpg]/ensure: createdNotice: /File[/var/www/cat-pictures/img/cat_003.jpg]/ensure: createdNotice: Finished catalog run in 0.08 seconds What just happened? First we created a top-level directory for the site files to live in: file { '/var/www/cat-pictures': ensure => directory,} We haven't seen a file resource before without either a source or a content attribute. ensure => directory will create a directory, as you might expect. If you said ensure => present instead, with no other attributes, Puppet would create an empty file. The following code is the part that does the heavy lifting: file { '/var/www/cat-pictures/img': source => 'puppet:///modules/cat-pictures/img', recurse => true, require => File['/var/www/cat-pictures'],} The source attribute is as you've used it before, but the recurse => true attribute tells Puppet to copy all files and directories contained in the source. This includes our handful of cat pictures, but it could be thousands of files in a tree of directories many levels deep. In practice Puppet is rather slow to manage large file trees, because it has to examine every file in the tree on every run to determine if it is up to date with the source. In this situation, you might be better of using Git, for example, to manage large trees of files. Using templates In a previous example we had Puppet deploy an Nginx virtual host file for the cat-pictures application. In this case we simply used a file resource with the cat-pictures.conf file distributed from Puppet. If we wanted to generalize this solution to manage many different websites, it would quickly become tedious to supply an almost identical virtual host file for each site, altering only the name and domain of the site. What we would prefer is to give Puppet a template file into which it could just insert these variables for each diferent site. The template function serves just this purpose. Anywhere you have multiple files that differ only slightly, or files that need to contain dynamic information, you can use a template.
Read more
  • 0
  • 0
  • 1594

article-image-aliens-have-landed
Packt
29 Jul 2013
28 min read
Save for later

The Aliens Have Landed!

Packt
29 Jul 2013
28 min read
(For more resources related to this topic, see here.) The progression of testing Way back when testing used to be primarily manual, test cases were created and executed by developers or quality assurance team members. These test cases would comprise of anything from simple unit tests (testing single methods or classes of code) or integration tests (testing multiple components within code) or even functional tests (tests that ensure the system performs as required). As we began to develop differently, whether it was from the agile project methodology or extreme programming methodologies, we needed more robust tools to support our needs. This led to the advent of automated testing. Instead of a tester working with your application and running tests against it, they could simply press a few buttons, hit a few key strokes, and execute a 100 or 200 test case suite against your application to see the functionality. In some realms, something called a test harness was used. Test harnesses usually included running the compiled application in some kind of a sandbox environment that was probably something like production (this is after all the final binary that would be rolled out) that may or may not have pointed to a database (if it did, and it was smart, it probably pointed to a completely non-discreet database instance) to perform some level of testing. User input would be simulated and a report (possibly in some cryptic format that only few understood) would be generated indicating whether the application did what was expected or not. Since then, new tools such as JUnit, Selenium, SoapUI to name a few, have been introduced to add more functionality to your test cases. These are meant to drive both unit and functional testing of your application. They are meant to be standard tools, easy to use and reuse, and overall a platform that many developers can work with, and can be a desirable skill set for employers. Standardizing of tools also allows for more integrations to occur; it may be difficult to get leverage to build an integration with your own built tools, with many developers wanting an integration with widely used frameworks A and B. What is Arquillian If you haven't heard of Arquillian before (or are very new to it), this may be the section for you. Arquillian is a testing framework for Java that leverages JUnit and TestNG to execute test cases against a Java container. The Arquillian framework is broken up into three major sections: test runners (JUnit or TestNG), containers (Weld, OpenWebBeans, Tomcat, Glassfish, and so on), and test enrichers (integration of your test case into the container that your code is running in). ShrinkWrap is an external dependency for you to use with Arquillian; they are almost sibling projects. ShrinkWrap helps you define your deployments, and your descriptors to be loaded to the Java container you are testing against. The JUnit test container is used throughout. If you'd like to use TestNG with your code, you simply need to replace the JUnit container with the TestNG container, and have your test classes extend the Arquillian class found there. The JUnit test cases use a JUnit Runner to start Arquillian. The containers used will vary with each case. The Arquillian difference Arquillian can be considered a standardized test harness for JVM-based applications. It abstracts the container or application start-up logic away from your unit tests and instead drives a deployment runtime paradigm with your application, allowing you to deploy your program, both via command line and to a Java EE application server. Arquillian allows you to deploy your application to your targeted runtime to execute test cases. Your targeted runtime can be an embedded application server (or series of libraries), a managed application server (where Arquillian performs the calls necessary to start and stop the JVM), or even a remote application server (which can be local to your machine, remote in your corporate infrastructure, or even the cloud). Arquillian fits in to certain areas of testing, which can vary based on testing strategies for your application. If you are using Java EE 6, you may want to use an embedded CDI container (such as Weld) to unit test parts of your application. These tests could happen hourly or every time someone commits a code change. You could also use Arquillian to automate your integration test cases, where you use a managed or embedded application server to run your application, or even just parts of your application. You can even use Arquillian to perform automated acceptance testing of your application, using other tools such as Selenium to drive requests through the user interface. This can also be used to smoke test deployments of applications. Arquillian can be used with a wide variety of containers that support everything from JBoss 4.2 (slightly pre-Java EE 5) through Java EE 6 and can control these containers in what Arquillian considers types – embedded, managed, and remote. Embedded application servers run within the same JVM as your test cases always do. Managed run within a separate JVM and are started and stopped by Arquillian. A managed container will start on the first test that requires a deployment and stop once all tests have been executed; there is no restart. Remote containers are as the name implies, remote JVMs. This could be on the same physical hardware that your test runs on or a remote piece of hardware that the application server runs on. The application server must be running in order to deploy. Note that if there is a problem deploying, such as the managed application server will not start or the remote application server will not start, Arquillian will fail once and assume that deployments will fail afterwards for the remaining test cases: Do not mix your unit test application servers that are used for automated testing and those that you use for manual testing. Whether it's a separate instance required, a distinct domain, profile, whichever your application server vendor supports, avoid mixing them. One of your biggest blockers may be from your manually deployed application interfering with your automated testing application. Even though remote application servers can be physically separated from your testing, they typically require the binaries to be locally available. Plan to have a copy of your application server available on your CI server(s) for this purpose. Prepare your application for this kind of testing. Whether it's the automatic deployment or undeployment of resources (JMS queues, JDBC connections, users, and so on) or ensuring that the server is up and running (for example, prebuild, kick off a kill, and restart process) make sure this can all happen from your build, either in your CI server or using scripts within your source repository. Do not try to reuse application servers across applications. If two test cases are running in parallel, you can run into inconsistent results. The fundamentals of a test case As our software has evolved, our strategy for testing it must evolve as well. We have become more dependent on techniques such as dependency injection (or inversion of control – IoC). When we take this in to consideration, we realize that our testing has to change. Take a look at the following example: @Testpublic void testCalculationOfBusinessData() {CalculatorData cd = new CalculatorData(1, 3, 5);CalculatorService ms = new CalculatorServiceImpl();ms.calculateSum(cd);assertEquals(1 + 3 + 5, cd.getResult());} We can assume that the method calculateSum takes the int values passed in to MyDataObject and sums up the values. As a result, when I construct it using 1, 3, 5 the total should come out to 9. This is a valid test case for our service layer, since our service layer knows what implementations exist out there and how they should be tested. If there was another implementation of CalculatorService that multiplied all results by 2, a separate test case or test class would exist which tested that object. Let's say we look at the business layer that invokes this service object: @Modelpublic class CalculatorController {@Injectprivate CalculatorService service;@Injectprivate CalculatorForm form;/**For the injected form, calculates the total of the input**/public void sum() {CalculatorData data = new CalculatorData(form.getX(),form.getY(),form.getZ());service.calculateSum(data);form.setSum(data.getCalculatedResult());}} This example uses JSR-330 annotations to inject references to CalculatorService, a service layer object that can perform basic calculator functions and CalculatorForm, some sort of UI component that has form input and output that can be read or returned. If we want to test this class, we will immediately run into a problem. Any invocation of the sum method outside of a JSR-330 (dependency injection for Java) container will result in a NullPointerException. So what does Arquillian do to make our test case more legitimate? Let's take a look at the test case and review the anatomy to understand that better: @RunWith(Arquillian.class)public class CalculatorTest {@Deploymentpublic static JavaArchive createArchive() {return ShrinkWrap.create(JavaArchive.class,"foo.jar").addAsManifestResource(EmptyAsset.INSTANCE,"beans.xml").addPackage(CalculatorData.class.getPackage());}@Inject CalculatorForm form;@Inject CalculatorController controller;@Testpublic void testInjectedCalculator() {form.setX(1);form.setY(3);form.setZ(5);controller.sum();assertEquals(9,form.getSum());}} There are a few pieces that make up this test case, each of which we'll need to review. These are given as follows: The @RunWith annotation: It tells JUnit to use the Arquillian runner for running this class. The @Deployment annotation: It tells Arquillian to use the specified archive for deployment purposes and testing purposes. The injection points: In this case, CDI injection points represent the objects under test. The Test: This is where we process the actual test case. Using the injected objects, we simulate form input by inserting values in X, Y, and Z in the form, then invoke the controller's sum method, which would be called from your user interface. We then validate that the resulting sum matches our expectations. What we gained was leveraging Arquillian to perform the same IoC injection that we would expect to see in our application. In addition, we have the following dependencies within our Maven pom file: <dependencyManagement> <dependencies> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-bom</artifactId> <version>2.0.0-alpha-1</version> <scope>import</scope> <type>pom</type> </dependency> <dependency> <groupId>org.jboss.arquillian</groupId> <artifactId>arquillian-bom</artifactId> <version>${org.arquillian.bom.version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.spec</groupId> <artifactId>jboss-javaee-6.0</artifactId> <version>1.0.0.Final</version> <type>pom</type> <scope>provided</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-impl-maven</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.arquillian.junit</groupId> <artifactId>arquillian-junit-container</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.arquillian.container</groupId> <artifactId>arquillian-weld-ee-embedded-1.1</artifactId> <version>1.0.0.CR3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.weld</groupId> <artifactId>weld-core</artifactId> <version>1.1.8.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.6.4</version> <scope>test</scope> </dependency> </dependencies> Our dependencies are as follows: Arquillian BOM: It's an overall list of all artifacts for running Arquillian ShrinkWrap: It's a separate API for creating deployments JUnit and Arquillian JUnit Container: Arquillian support for working with JUnit Arquillian Weld EE: Arquillian containers control what your deployment runtime should be Testing profiles One of the benefits of using Arquillian with Maven is that you can control how your tests execute using Maven profiles. With this approach, you can define a profile per container to test against. In some cases, you may want to test your application or library against multiple containers. This allows you to reuse deployments against different libraries. We still remain with the core limitation: you can only have one container on your classpath at a time. Let's suppose we take this same application, but want to run it against Apache OpenWebBeans as well as Weld. Each Arquillian container has a default Maven profile configuration that can be used for testing. These containers are covered within the Arquillian documentation, found at https://docs.jboss.org/author/display/ARQ/Container+adapters. Steps to try out containers are given as follows: Import the configuration defined by the container definition. Run a mvn clean install Pconfiguration_name. You can choose to set a default profile as well if you like. If you don't choose a default profile, you will need to specify one every time you want to run tests. Running the tests for this project, for both the weld-ee-embedded-1.1 container and the openwebbeans-embedded-1 profile should result in the same thing – a working test suite that is valid in both implementations. At the time of writing, I used Weld 1.1.8.Final and OpenWebBeans 1.1.3. It is important to point out at this time that these profile names are only useful if your application is designed purely for cross-platform testing and you want to run all test cases against each individual platform. If your application only targets a single platform, you may want to derive test cases that run on that platform as well as any subcomponents of that platform (for example, if you are a WebSphere v8 user, you may want your unit tests against OpenWebBeans and integration against WebSphere; however, if you are a WebLogic user, you would want to use Weld and WebLogic for your testing). Typically, when it comes to testing, you will use a distinct Maven profile to cover your stages of testing. You should set up a default Maven profile that runs only your basic tests (your unit tests); this will be set as activeByDefault. This should include any testing dependencies needed to run only these unit tests. You may optionally choose to only run certain parts of your test suite, which could be distinct packages under src/test/java or even standalone projects that are children to your parent that are only run under certain circumstances. I prefer the former approach, since the usage of conditional child projects can become confusing for developers. Profiles are useful for conditional dependencies, since they do include a dependency and dependencyManagement section in their pom files. You can also avoid dependency leaking. For example, most applications require the use of the full Java EE 6 APIs, but including these APIs with your Glassfish build will cause your tests to fail. Likewise, deploying to a managed application server may require different APIs than deploying to a remote application server. Categorizing your test cases One thing that Arquillian ultimately derives is that names mean everything. There are two naming schemes that you should follow always, they relate to the questions "what" and "how". What components are you testing? What phase of testing are you under? How does this class relate to your test cases? How is this code being deployed? These questions really pop up due to the nature of Arquillian, and really show off its robustness. Considering some of the main testing phases, unit test, integration test, system test, compatibility test, smoke test, acceptance test, performance test, usability test should all relate to specific packages in your test code. Here's a proposed naming scheme. I will assume that your code starts with com.mycompany.fooapp where com.mycompany is your company's domain, fooapp is the name of your application. You may have packages below this such as com.mycompany.fooapp.model or com.mycompany.fooapp.controller or even com.mycompany.fooapp.modulea.controller all of which represent varying testing scenarios that you may consider. com.mycompany.fooapp.test: This is the parent package for all test classes. There may or may not be any classes in this package. com.mycompany.fooapp.test.utils: This is where all of your test utility code goes. This would be where any deployments are actually build, but invoked from your test classes. com.mycompany.fooapp.test.unit: This is where all unit tests should exist. The packages/classes under test should fall relative under here. For example, com.mycompany.fooapp.test.unit.controller should test your controller logic. com.mycompany.fooapp.test.integration: Likewise, all integration test cases should fall under here. Following this pattern, you can derive your functional, acceptance, usability, and so on test case names. Following this pattern, you can easily define Maven profiles within your projects to test out your various layers. Let's suppose you want to define a unittest profile where the build includes running all unit tests (usually light weight tests, that maybe use an embedded container with Arquillian), you could do something like this: <profile><activation><activeByDefault>true</activeByDefault></activation><id>unittest</id><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><includes><include>**/unit/**</include></includes></configuration></plugin></plugins></build></profile> This will tell Maven to only run the tests in the unit test packages by default. This allows your builds to go by quickly and test key components of your code when needed. Since it's active by default, you would get these tests run anytime you kick off mvn install or mvn test from the command line, or your continuous integration server. Likewise, you may want to run more tests during your integration testing or system testing phases. These may or may not overlap with one another, but would likely include your unit tests as well. You could use the following, very similar Maven profile to achieve that: <profile><id>integrationtest</id><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><includes><include>**/unit/**</include><include>**/integration/**</include><include>**/system/**</include><include>**/regression/**</include></includes></configuration></plugin></plugins></build></profile> With the way this profile is configured, any time you invoke mvn test – integrationtest you will run all unit, integration, system, and regression test cases. These tests will probably take a while. If you're lucky and your application server supports an embedded mode it probably has a quick start up/shutdown. These tests may be running against a remote container though, so the deployment and execution time may take longer. Enriching your tests One of the core principles noted in the demo test case is that we injected a reference to the business object being tested, which itself had injection points as well that were satisfied. There are three core injection points supported by default with Arquillian, though others are supported by extensions as well as some custom injection points defined by Arquillian itself. They are as follows: @Resource: It defines references to any JNDI entry as per standard naming and injection schemes. @EJB: As long as you are including a deployed EJB in your archive, you can refer to it as long as your target container includes EJB support. EJB JNDI entry conventions remain intact. It is also worthwhile to note that Local and Remote interfaces matter. When you deploy to a same JVM application server, or a remote application server you must ensure that your injected test cases can see the EJB reference appropriately. @Inject: This is available as long as you have deployed a valid bean archive (requires beans.xml in META-INF or WEB-INF). Running out of the container Sometimes you will need to mix your Arquillian tests with non Arquillian tests, or sometimes you have special test cases that require a deployment but should not be run with that deployment (simulating a remote client to that deployment, for example). This may include a set of unit tests that have deployments to the container and some that do not require this. You can run the test outside of the container JVM by using the @RunAsClient annotation. This can be done at the class level or at the method level, allowing you to have multiple run-types within a single test class. This approach would be useful if you want to test a web service client, either SOAP or a REST API, ensuring that you are executing outside of the container JVM for your client. One of the custom injection points that Arquillian supports is a @ArquillianResource URL baseUrl; this represents the base URL of a remote container deployment that you can use in your client-level tests. The ArquillianResource annotation supports an additional value attribute that can be the class of a Servlet deployed in case you have multiple deployments occurring as a part of your test. Once you have the URL for your application deployment, you can build the location of your web services to be able to use your client application for testing purposes. This would also be used if you wanted to functionally test your application via HTTP, perhaps using Selenium as the driver for the application. The other types of objects available for injection using this annotation are the Deployer used and the InitialContext of the remote application server. The deployer gives you access to the underlying deployment while InitialContext would allow you to look up remote objects – for example, EJBs, JMS Queues/Topics/ConnectionFactories, or any other remotely accessible resource. Efficient test authoring Now that we have a test that can run against multiple containers, we need to start adding more test cases to our suite. When we do this, we have to keep two key elements in mind. Don't repeat yourself, and don't bloat your software. In many of our applications, we have a number of components that make up various layers. Some of them are dependent on one another, others are more generic. One of the key things to think about when planning your Arquillian testing is how should your JAR files look. Let's suppose we have an entire data object layer that has dependencies all throughout your application. We must have those classes in every test case. However, we can usually skip to only certain controllers and business beans within their specific test cases. Remember to create utilities to define your object structure, this gives you a single entry point for creating your deployment archive and allows for better extensibility. Here is a prototype class that can be used to start, it supports creating both a JAR file as well as a full web application: public class TestUtils {public static JavaArchive createBasicJar() {return ShrinkWrap.create(JavaArchive.class,"test.jar").addAsManifestResource(EmptyAsset.INSTANCE,"beans.xml").addPackages(false,getCorePackages());}public static WebArchive createWebApp() {return ShrinkWrap.create(WebArchive.class,"test.war").addAsWebInfResource(EmptyAsset.INSTANCE,"beans.xml").addPackages(false,getCorePackages());}public static Package[] getCorePackages() {return new Package[]{CalculatorData.class.getPackage()};}} What these methods add is a significant reduction in code that is impacted by a package change, or code refactoring in your primary code base. Let's suppose that we want to extend getCorePackages to also take in a number of classes, which when added, add the entire package to the deployment: public static Package[] getCorePackages(Class<?>...classes) {List<Package> packages = new ArrayList<Package>();if(classes != null) {for(Class<?> c : classes) {packages.add(c.getPackage());}}packages.add(CalculatorData.class.getPackage());return packages.toArray(new Package[]{});} One benefit that we have using this approach is that anyone who was using getCorePackages() does not need to change their code, since the argument is not required. Note that the ShrinkWrap API has several addPackage/addPackages methods. This one used has a first argument, Boolean, whether to re-curse through child packages to find your code. Going back a few pages to some naming conventions I proposed, what would happen if you add the package com.mycompany.fooapp to your bundle? All of your application classes, including test classes, would be added to the deployment you are creating. This is probably not what you would have expected, as a result, the recommendation is to not re-curse into child packages and instead just list out each package you want added explicitly. Another option to consider is to have your test classes delegate their work. Commonly thought of as the façade programming paradigm, you can actually apply this to your test code as well. If you have code that should be tested distinctly but use different deployments you may want to use distinct deployment objects but reuse your test case. This may involve using a controller type test case that simply delegates its test calls to another object that is meant to purely handle the testing logic. Your controller would have methods annotated @Test and include your @Deployment(s) but would delegate logic to another class, potentially an injected test executor class. ShrinkWrap – building your own app One of the more curious things about Arquillian is that your test case is responsible for constructing the application to be deployed. When you're working with Maven it is especially odd, since all of the information to build the application is there, either implicitly based on the project structure or explicitly listed in your pom file. There are two realizations around this that are important: Your test cases are meant to test anything from a subset of your code to your entire application. Arquillian is flexible enough to handle both extremes. Arquillian works great with Maven, but also works with other build tools such as Ant and Gradle. In order to support the dynamic generation of your application, the ShrinkWrap project exists to help dynamically build Java archive files. There are four primary archive types supported in ShrinkWrap: Java Archive (plain JAR files), Web Archive (WAR files), Enterprise Archive (EAR files), and Resource Adapters (RARs). Your Arquillian test case can declare any number of these archive files to be created for testing purposes. Another place that ShrinkWrap helps with is the creation of deployment descriptors. These could be application.xml files, or persistence.xml files, or any of the standard deployment descriptors that you would use in your application. Likewise, it has extensibility built in to allow the creation of new descriptors in a programmatic fashion. This article assumes that you are using the ShrinkWrap 2.0 APIs; one of the key features added is support for resolving dependency files from reading a Maven pom file. Another key thing you need to do is modify your test classpath to include some files from your core application. Here is an example of what to do, from another project I was working on recently: <testResources><testResource><directory>src/test/resources</directory></testResource><testResource><directory>src/main/resources</directory></testResource><testResource><directory>src/main/webapp/WEB-INF</directory><targetPath>web</targetPath></testResource></testResources> This will make it easier to reference your main application resources without requiring full paths or file manipulation. ShrinkWrap also provides ways to build deployment descriptors. This is a programmatic approach to adding the descriptor to your deployment, including programmatically creating the descriptor. Because of the need to test using the same descriptors being built with the production application, I have found it easier to reference to an existing descriptor. However, in some cases it may make more sense to use one customized to your test applications. In this scenario, I would strongly recommend creating a utility method to build the descriptor. To do this, we will add the following to our Maven pom.xml in the dependencyManagement section: <dependency><groupId>org.jboss.shrinkwrap.descriptors</groupId><artifactId>shrinkwrap-descriptors-bom</artifactId><version>2.0.0-alpha-4</version><scope>import</scope><type>pom</type></dependency> Declare the following dependency: <dependency><groupId>org.jboss.shrinkwrap.descriptors</groupId><artifactId>shrinkwrap-descriptors-impl-javaee</artifactId></dependency> Then add the following method to our code: public static StringAsset createWebXml() {return new StringAsset(Descriptors.create(WebAppDescriptor.class).exportAsString());}public static WebArchive createWebApp() {return ShrinkWrap.create(WebArchive.class,"test.war").addAsWebInfResource(EmptyAsset.INSTANCE,"beans.xml").addAsWebInfResource(createWebXml(), "web.xml").addPackages(false,getCorePackages());} This will generate the web.xml file expected for your test case. One of the benefits of using the descriptors is that we can actually import the one from our application and make changes as needed. public static StringAsset createWebXml() {WebAppDescriptor descriptor = Descriptors.importAs(WebAppDescriptor.class).fromFile(new File("web/web.xml"));descriptor.createWelcomeFileList().welcomeFile("someFile.jsp");return new StringAsset(descriptor.exportAsString());} As a result, this will use your base web.xml file but change the welcome file to something else. You can do this with a number of other descriptors, including persistence.xml, beans.xml, web-fragment.xml, and so on. Getting the most from Arquillian Arquillian does take some understanding to work with. In order to get the most from it, you have to work with it and invest time. Your standard rules still apply. Arquillian does not use any special rules when it comes to processing deployments. The rules about deployment descriptors, archive contents, and so on and so forth still apply. You need to keep the rule of thumb – if it deploys to your application server, then you can deploy the same archive via Arquillian; just make sure that you are deploying the same archive. Note that you can use the Archive's toString method to print out the contents when in doubt. This supports a formatter as well, to make it easier to read the contents. Alternatively, you can export an Archive using archive.as(ZipExporter.class).exportTo(File) if you want to manually review the file. Run as many tests as you can with Arquillian. Due to Arquillian's nature, you're going to start to find inconsistencies in your code if you don't test it with Arquillian. This could include unexpected dependency injection expectations, which Arquillian will process for you. Arquillian, since it executes your code the way the application server would as requests come in, makes your tests more consistent with the real world of how the code works. Testing more in Arquillian, even if it is just using a basic CDI container or OpenEJB container, will allow you to test more effectively. You make the best use of Arquillian when you use it throughout 100 percent of your test cases. Finally, my last key advice to getting the most from Arquillian is to remember to not over-complicate your build to make use of Arquillian. Arquillian works fine as a part of your standard build. It has no requirement to create distinct projects for each build type or make overly complicated build structures on top of your application. If you are attempting to run Arquillian with your continuous integration server, then you must ensure that different test cases run either as different steps of the build or as separate build jobs. Arquillian extensions There are a number of extensions available for Arquillian; they are designed to extend Arquillian functionality to do some domain-specific testing: Persistence, using DBUnit and validating that results of interacting with the database. REST, invoke REST APIs from Arquillian the were deployed as a part of the test case. Spring, use a Spring Context and additional Spring libraries with your test cases. Drone/Selenium, functionally test your web applications using Arquillian. Summary My main goal in this article was to give you an overview of Arquillian and introduce you to some of its core concepts. Resources for Article: Further resources on this subject: So, what is Spring for Android? [Article] Web Services Testing and soapUI [Article] SOAP and PHP 5 [Article]
Read more
  • 0
  • 0
  • 1846
article-image-building-app-using-backbonejs
Packt
29 Jul 2013
7 min read
Save for later

Building an app using Backbone.js

Packt
29 Jul 2013
7 min read
(For more resources related to this topic, see here.) Building a Hello World app For building the app you will need the necessary script files and a project directory laid out. Let's begin writing some code. This code will require all scripts to be accessible; otherwise we'll see some error messages. We'll also go over the Web Inspector and use it to interact with our applications. Learning this tool is essential for any web application developer to proficiently debug (and even write new code for) their application. Step 1 – adding code to the document Add the following code to the index.html file. I'm assuming the use of LoDash and Zepto, so you'll want to update the code accordingly: <!DOCTYPE HTML> <html> <head> <title>Backbone Application Development Starter</title> <!-- Your Utility Library --> <script src ="scripts/lodash-1.3.1.js"></script> <!-- Your Selector Engine --> <script src ="scripts/zepto-1.0.js"></script> <script src ="scripts/backbone-1.0.0.js"></script> </head> <body> <div id="display"> <div class ="listing">Houston, we have a problem.</div> </div> </body> <script src ="scripts/main.js"></script> </html> This file will load all of our scripts and has a simple <div>, which displays some content. I have placed the loading of our main.js file after the closing <body> tag. This is just a personal preference of mine; it will ensure that the script is executed after the elements of the DOM have been populated. If you were to place it adjacent to the other scripts, you would need to encapsulate the contents of the script with a function call so that it gets run after the DOM has loaded; otherwise, when the script runs and tries to find the div#display element, it will fail. Step 2 – adding code to the main script Now, add the following code to your scripts/main.js file: var object = {};_.extend(object, Backbone.Events);object.on("show-message", function(msg) {$('#display .listing').text(msg);});object.trigger("show-message", "Hello World"); Allow me to break down the contents of main.js so that you know what each line does. var object = {}; The preceding line should be pretty obvious. We're just creating a new object, aptly named object, which contains no attributes. _.extend(object, Backbone.Events); The preceding line is where the magic starts to happen. The utility library provides us with many functions, one of which is extend. This function takes two or more objects as its arguments, copies the attributes from them, and appends them to the first object. You can think of this as sort of extending a class in a classical language (such as PHP). Using the extend utility function is the preferred way of adding Backbone functionality to your classes. In this case, our object is now a Backbone Event object, which means it can be used for triggering events and running callback functions when an event is triggered. By extending your objects in this manner, you have a common method for performing event-based actions in your code, without having to write one-off implementations. object.on("show-message", function(msg) {$('#display .listing').text(msg);}); The preceding code adds an event listener to our object. The first argument to the on function is the name of the event, in this case show-message. This is a simple string that describes the event you are listening for and will be used later for triggering the events. There isn't a requirement as far as naming conventions go, but try to be descriptive and consistent. The second argument is a callback function, which takes an argument that can be set at the time the event is triggered. The callback function here is pretty simple; it just queries the DOM using our selector engine and updates the text of the element to be the text passed into the e vent. object.trigger("show-message", "Hello World"); Finally, we trigger our event. Simply use the trigger function on the object, tell it that we are triggering the show-message event, and pass in the argument for the trigger callback as the second argument. Step 3 – opening the project in your browser This will show us the text Hello World when we open our index.html file in our browser. Don't believe me? Double click on the file now, and you should see the following screen: If Chrome isn't your default browser, you should be able to right-click on the file from within your file browser and there should be a way to choose which application to open the file with. Chrome should be in that list if it was installed properly. Step 4 – encountering a problem Do you see something other than our happy Hello World message? The code is set up in a way that it should display the message Houston , we have a problem if something were to go wrong (this text is what is displayed in the DOM by default, before having JavaScript run and replace it). The missing script file The first place to look for the problem is the Network tab of the Web Inspector. This tab shows us each of the files that were downloaded by the browser to satisfy the rendering of the page. Sometimes, the Console tab will also tell us when a file wasn't properly downloaded, but not always. The following screenshot explains this: If you look at the Network tab, you can see an item clearly marked in red ( backbone-1.0.0.js ). In my project folder, I had forgotten to download the Backbone library file, thus the browser wasn't able to load the file. Note that we are loading the file from the local filesystem, so the status column says either Success or Failure . If these files were being loaded from a real web server, you would see the actual HTTP status codes, such as 200 OK for a successful file download or 404 Not Found for a missing file. The script typo Perhaps you have made a typo in the script while copying it from the book. If you have any sort of issues resulting from incorrect JavaScript, they will be visible in the Console tab, as shown in the following screenshot: In my example, I had forgotten the line about extending my object with the Backbone events class. Having left out the extend line of code caused the object to be missing some functionality, specifically the method on(). Notice how the console displays which filename and line number the error is on. Feel free to remove and add code to the files and refresh the page to get a feel for what the errors look like in the console. This is a great way to get a feel for debugging Backbone-based (and, really, any JavaScript) applications. Summary In this article we learned how to develop an app using Backbone.js. Resources for Article : Further resources on this subject: JBoss Portals and AJAX - Part 1 [Article] Getting Started with Zombie.js [Article] DWR Java AJAX User Interface: Basic Elements (Part 1) [Article]
Read more
  • 0
  • 0
  • 8383

article-image-creating-your-first-freemarker-template
Packt
26 Jul 2013
10 min read
Save for later

Creating your first FreeMarker Template

Packt
26 Jul 2013
10 min read
(For more resources related to this topic, see here.) Step 1 – setting up your development directory If you haven't done so, create a directory to work in. I'm going to keep this as simple as possible, so we won't need a complicated directory structure. Everything can be done in one directory.Put the freemarker.jar in the directory. All future talk about files and running from the command-line will refer to your working directory. If you want to, you can set up a more advanced project-like set of directories. Step 2 – writing your first template This is a quick start, so let's just dive in and write the template. Open a file for editing called hello.ftl. The ftl extension is customary for FreeMarker Template Language files, but you are free to name your template files anything you want. Put this line in your file: Hello, ${name}! FreeMarker will replace the ${name} expression with the value of an element called name in the model. FreeMarker calls this an interpolation. I prefer to refer to this as "evaluating an expression", but you will encounter the term interpolation in the documentation. Everything else you have put in this initial template is static text. If name contained the value World, then this template would evaluate to: Hello, World! Step 3 – writing the Java code Templates are not scripts that can be run, so we need to write some Java code to invoke the FreeMarker engine and combine the template with a populated model. Here is that code: import java.io.*;import java.util.*;import freemarker.template.*;public class HelloFreemarker { public static void main(String[] args) throws IOException, TemplateException { Configuration cfg = new Configuration(); cfg.setObjectWrapper(new DefaultObjectWrapper()); cfg.setDirectoryForTemplateLoading(new File(".")); Map<String, Object> model = new HashMap<String, Object>(); model.put("name", "World"); Template template = cfg.getTemplate("hello.ftl"); template.process(model, new OutputStreamWriter(System.out)); }} The highlighted line says that FreeMarker should look for FTL files in the "working directory" where the program is run as a simple Java application. If you set your project up differently, or run in an IDE, you may need to change this to an absolute path. The first thing we do is create a FreeMarker freemarker.template.Configuration object. This acts as a factory for freemarker.template.Template objects. FreeMarker has its own internal object types that it uses to extract values from the model.In order to use the objects that you supply, it must wrap these in its own native types. The job of doing this is done by an object wrapper. You must provide an object wrapper. It will always be FreeMarker's own freemarker.template.DefaultObjectWrapper unless you havespecial object wrapping requirements. Finally, we set the root directory for loading templates. For the purposes of our sample code, everything is in the same directory so we just set it to ".". Setting the template directory can throw an java.lang.IOException exception in this code. We simply allow that to be thrown out of the method. Next, we create our model, which is a simple map of java.lang.String keys to java.lang.Object values. The values can be simple object types such as String or java.lang.Number, or they can be complex object types, including arrays and collections. Our needs are simple here, so we're going to map "name" to the string "World". The next step is to get a Template object. We ask the Configuration instance to load the template into a Template object. This can also throw an IOException. The magic finally happens when we ask the Template instance to process the model and create an output. We already have the model, but where does the output go? For this, we need an implementation of java.io.Writer. For convenience, we are going to wrap the java.io.PrintWriter in java.lang.System.out with a java.io.OutputStreamWriter and give that to the template. After compiling this program, we can run it from the command line: java -cp .;freemarker.jar HelloFreemarker For Linux or OSX, you would use a ":" instead of a ";" in the command: java -cp .:freemarker.jar HelloFreemarker The result should be that the program prints out: Hello, World! Step 4 – moving beyond strings If you plan to create simple templates populated with preformatted text, then you now know all you need to know about FreeMarker. Chances are that you will, so let's take a look at how FreeMarker handles formatting other types and complex objects. Let's try binding the "name" object in our model to some other types of objects. We can replace: model.put("name", "World"); with: model.put("name", 123456789); The output format of the program will depend on the default locale, so if you are in the United States, you will see this: Hello, 123,456,789! If your default locale was set to Germany, you would see this: Hello, 123.456.789! FreeMarker does not call toString() method on instances of Number types it employs java.text.DecimalFormat. Unless you want to pass all of your values to FreeMarker as preformatted strings, you are going to need to understand how to control the way FreeMarker converts values to text. If preformatting all of the items in your model sounds like a good idea, it isn't. Moving "view" logic into your "controller" code is a sure-fre way to make updating the appearance of your site into a painful experience. Step 5 – formatting different types In the previous section, we saw how FreeMarker will choose a default method of formatting numbers. One of the features of this method is that it employs grouping separators: a comma or a period every three digits. It may also use a comma rather than a period to denote the decimal portion of the number. This is great for humans who may expect these formatting details, but if your number is destined to be parsed by a computer, it needs to be free of grouping separators and it must use a period as a decimal point. In this case, you need a way to control how FreeMarker decides to format a number. In order to control exactly how model objects are converted to text FreeMarker provides operators called built-ins. Let's create a new template called types.ftl and put in some expressions that use built-ins to control formatting: String: ${string?html}Number: ${number?c}Boolean: ${boolean?string("+++++", "-----")}Date: ${.now?time}Complex: ${object} The value .now come is a special variable that is automatically provided by FreeMarker. It contains the date and time when the Template began processing. There are other special variables, but this is the only one you're likely to use. This template is a little more complicated than the last template. The " ?" at the end of a variable name denotes the use of a built-in. Before we explore these particular built-ins, let's see them in action. Create a java program, FreemarkerTypes, which populates a model with values for our new template: import java.io.*;import java.math.BigDecimal;import java.util.*;import freemarker.template.*;public class FreemarkerTypes { public static void main(String[] args) throws IOException, TemplateException { Configuration cfg = new Configuration(); cfg.setObjectWrapper(new DefaultObjectWrapper()); cfg.setDirectoryForTemplateLoading(new File(".")); Map<String, Object> model = new HashMap<String, Object>(); model.put("string", "easy & fast "); model.put("number", new BigDecimal("1234.5678")); model.put("boolean", true); model.put("object", Locale.US); Template template = cfg.getTemplate("types.ftl"); template.process(model, new OutputStreamWriter(System.out)); }} Run the FreemarkerType program the same way you ran HelloFreemarker. You will see this output: String: easy &amp; fastNumber: 1234.5678Boolean: +++++Date: 9:12:33 AMComplex: en_US Let's walk through the template and see how the built-ins affected the output. Our purpose is to get a solid foundation in the basics. We'll look at more details about how to use FreeMarker features in later articles. First we output a String modified with the html built-in. This encoded the string for HTML, turning the & into the &amp; HTML entity. You will want this applied to a lot of your expressions on HTML pages in order to ensure proper display of your text and to prevent cross-site scripting ( XSS ) attacks. The second line outputs a number with the c built-in. This tells FreeMarker that the number should be written for parsing by computers. As we saw in the previous section, FreeMarker will by default format numbers with grouping separators. It will also localize the decimal point, using a comma instead of a period. This is great when you are displaying numbers to humans, but not computers. If you want to put an ID number in a URL or a price in an XML document, you will want to use this built-in to format it. Next, we format a Boolean. It may surprise you to learn that unless you use the string built-in, FreeMarker will not format a Boolean value at all. In fact, it throws an exception. Conceptually, "true" and "false" have no universal text representation. If you use string with no arguments, the interpolation will evaluate to either "true" or "false", but this is a default you can change. Here, we have told the built-in to use a series of + characters for "true" and a series of – characters for "false". Another type which FreeMarker will not process without a built-in is java.util.Date. The main issue here is that FreeMarker doesn't know whether you want to display a date, a time, or both. By specifying the time built-in we are letting FreeMarker know that we want to display a time. The output shown previously was generated shortly past nine o'clock in the morning. Finally, we see a complex object converted to text with no built-ins. Complex objects are turned into text by calling their toString() method, so you can use string built-ins on them. Step 6 – where do we go from here? We've reached the end of the Quick start section. You've created two simple templates and worked with some of the basic features of FreeMarker. You might be wondering what are the other built-ins, or what options they offer. In the upcoming sections we'll look at these options and also ways to change the default behavior. Another issue we've glossed over is errors. Once you have applied some of these built-ins, you must make sure that you supply the correct types for the named model elements. We also haven't looked at what happens when a referenced model element is missing. The FreeMarker manual provides excellent reference for all of this. Rather than trying to find your way around on your own, we'll take a guided tour through the important features in the Top Features section of the article. Quick start versus slow start A key difference between the Quick start and Top Features sections is that we'll be starting with the sample output. In this article, we created templates and evaluated them to see what we would get. In a real-world project, you will get better results if you worked backwards from the desired result. In many cases, you won't have a choice. The sample output will be generated by web designers and you will be expected to produce the same HTML with dynamic content. In other cases, you will need to work from mock-ups and decide the HTML for yourself. In these cases, it is still worth creating a static sample document. These static samples will show you where you need to apply some of the techniques. Summary In this article, we discussed how to create a freemarker template. Resources for Article: Further resources on this subject: Getting Started with the Alfresco Records Management Module [Article] Installing Alfresco Software Development Kit (SDK) [Article] Apache Felix Gogo [Article]
Read more
  • 0
  • 0
  • 7222
Modal Close icon
Modal Close icon