Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-dotnetnuke-skinning-creating-your-first-skin
Packt
23 Oct 2009
12 min read
Save for later

DotNetNuke Skinning: Creating Your First Skin

Packt
23 Oct 2009
12 min read
Choosing an Editor If this is your first skin, you really should be thinking about what editor you will be using. If you don't already have an editor or the development environment for other coding you may be working with, the immediate choice that may come to mind is Microsoft Notepad, but there's no need to put yourself through that type of abuse. As we're working with Microsoft technologies while working with DotNetNuke, the natural choice will be Microsoft Visual Web Developer (VWD) which is free. There are other choices for editors here, but VWD will be the one used by most in this context, so we'll move on with it in our examples. If you are using Microsoft's VisualStudio .NET (Microsoft's premier development environment), you will notice that the screens and menus are virtually the same. Installing Visual Web Developer Before we can do anything, we'll need VWD installed. If you have already installed VWD, feel free to skip this section. These are the steps for getting VWD installed: Be sure you have version 2.0 of the .net framework. This can be downloaded from http://www.asp.net or with Windows Updates. Download the VWD install file from http://www.asp.net from the Downloads section. The file will be about three megabytes in size. Once on your local drive, double-click on the fi le to run the installation. You will encounter several common wizard screens. One wizard screen to notein particular is for installing SQL Server 2005 Express Edition. If you do not already have a version of SQL Server 2005 installed, be sure to select to install this. DotNetNuke will have to have an edition of this to run off for it's data store. This is a screen shot of the recommended installation options to choose. Stepping through the wizard, you will start the installation. The installation process may take a while depending upon what options you chose. For example, if you chose to install the MSDN library (documentation & helpfiles), it will take much longer. It will only download the items it needs. At the end of the installation, it will prompt you to register the software. If you do not register VWD within thirty days, it will stop working. If you encounter problems in the installation of VWD, you can find additional assistance at the http://forums.asp.net/discussion website. Installing the DotNetNuke Starter Kits E ven though we now have VWD and SQL Server, we'll need the DotNetNuke files to set up before we can start skinning portals. Do so by using the following steps: Navigate to http://www.dotnetnuke.com. If you haven't already registered on this site, do so now. If you are not already logged in, do so now. Click on Downloads and download the latest version of the starter kit. Right-click on the zip file you downloaded and extract the contents. Double-click on the vscontent file that was extracted. This will start theVisual Studio Content Installer. Select all the components, and click Next. Click Finish to install the starter kit. There are a few components that will be installed. See that in the next screenshot one of the components did not get installed. This is fine as long as the first one, DotNetNuke Web Application(the one we'll be using) installed successfully. The following is what you should see so far: If you encounter problems in the installation of the DotNetNuke starter kits, you can find additional assistance at the http://www.dotnetnuke.com website by clicking on the Forums link and then drilling-down to the Install It! link. Setting Up Your Development Environment In almost any programming project, you will have two environments: the development environment and the post-deployed environment. While skinning, this is no different. Most likely, you will have a local computer where you work on your skin. When you are done with it and are ready to package and deploy it, itwill be installed on the target or live DotNetNuke website which will be your post-deployed environment. To set up our development environment, fire up VWD. We'll now create a new DotNetNuke install: Click on File, and then click New Web Site. A dialog box appears. Click on DotNetNuke Web Application Framework. For Location, pick File System (should be the default item), then type the following location beside it: C:DotNetNukeSkinning. This is the screenshot of what you should see so far: Click OK. It will take a few moments to copy over all the needed web files. You will then be presented with a welcome screen. As the welcome page directs, press Ctrl plus F5 to run your DotNetNuke application. After a few moments, a DotNetNuke install should open in a web browser. If you are presented with the following message, right-click on the information bar at the top and enable the intranet settings in the Internet Explorer.This is what you should see at this point: You are presented with a choice of installation methods. Select Auto andthen select Next. You should then see a web page with a log of installation of the application.Click on the link at the bottom that says Click Here To Access Your Portal. If you encounter problems in the installation of the DotNetNuke, you can find additional assistance at the http://www.dotnetnuke.com website by clicking on the Forums link and then drilling-down to the Install It! link. Congratulations! You now have DotNetNuke up and running. Click Login in the upper-right corner of the screen with the username as host and a password as dnnhost. You should be on the Home page with several modules on it. To make the home page easier to work with, delete all the modules on it, and add a blank Text/HTML module. (In case you have never deleted a module from a page before, you will find the delete menu item if you hover over the downward-pointing triangles to the left of each of the titles.) Depending on the version of DNN you downloaded, you may experienced system message from DotNetNuke on the Home page titled Insecureaccount details. Although changing the default password as it instructs is always a good idea, it is not necessary on a development computer or a non-production implementation of DotNetNuke. However, if you don't want it to nag you about it go ahead and change it. This is our DotNetNuke portal that we will use to test the skins we will create. Move back over to VWD. Close the welcome page. The skins for DotNetNuke will be found in ~Portals_defaultSkins. Go to that directory now as shown here: Congratulations! You have now set up your development environment, and we are now ready for skinning. Creating Your First Skin We will now create a skin and record time. You may be impressed by how fast and easy it is for you to create a skin. Remember when we downloaded the starter kits from DotNetNuke.com? One template is for creating a skin. As of the time of this writing, the current download's template will produce a skin that looks just like the default skin. If this is what you're looking for, you can achieve the same result by copying the DNN-Blue folder and renaming it to something else. Rather than doing this, however, we are starting from scratch. Creat e a folder in your development environment. Name it as FirstSkin. InVWD, to create a new folder, right-click on the folder you want to create it in—in this case Skins—and select New Folder. Next, create an htm file inside the FirstSkin folder called Skin.htm. Use the File menu to create a New File. This will bring up a dialog box where you will pick what type of file you wish to create. Pick HTML Page and name the file as Skin.htm. Now, open our new Skin.htm file. A typical htm document will have tags like , , and . A DotNetNuke skin has none of these. Delete any content so you have clean slate to start from. Once we have a blank htm page to work from, type in the following and save: [LOGIN][MENU]<div id="ContentPane" runat="server"></div> Go to the Skins menu item on your Admin menu. You will now see two drop-down boxes, one for Skins and one for Containers. In the drop-down for Skins, pick the skin you have created. You should see something like this: Click on the link in the lower-middle portion of the screen that says ParseSkin Package. You should see your skin now: Now that our skin has been parsed, let's apply it to our current DotNetNuke portal by clicking on the Apply link. Keep in mind that we only have one pane, the ContentPane. If this was a live site with modules on other panes, the positions may have been changed. Now, go to the home page by clicking on your menu bar at the top. What Do We Have Here? I know what you're thinking: This has got to be the world's simplest DotNetNuke skin. And you're right. You may not be rushing to install this skin on your production portals, but you have created your very first operational skin! Let's go over what just happened, from creating our skin to seeing it in action. Skinsstart out as a simple HTML file. Just as with any website, an HTML file will have some degree of markup. Of course, we have not added much markup to our skin yet. If you're wondering from where DotNetNuke gets all the HTML structure such as the html, head, and body tags, take a look at Default.aspx in the root of your DNN install. This is the page used essentially everytime a page is served up. You can look in that file and find an ASP.NET element called SkinPlaceHolder. This is where our skin will be injected into each DotNetNuke page. Everything before and after this place holder is what will be served to any DNN page request no matter what skin is applied. The code we entered for our skin is: [LOGIN][MENU]<div id="ContentPane" runat="server"></div> Of the code we typed, [LOGIN] and [MENU] are special keywords to DotNetNuke,called tokens. The [Login] token will turn into the login link you're used to seeing and the [Menu] token will serve as our DotNetNuke menu. Adding the [login] token will ensure that we're not locked out of our portal after applying this skin. The <div> tag we added will be a simple ContentPane for now. Notice the two attributes we added to this tag <div><em>—id and runat. These are attributes required by ASP.NET. The id is a unique identifier in the page and the value given to it (ContentPane) is recognized as name by DotNetNuke. The runat attribute tells the ASP.NET engine that it needs to be processed by it. Why Parse? Recall when we clicked on a link to parse our skin. What DotNetNuke does at this point is take our HTM file and replace those tokens with ASP.NET user controlsthat have been predefined in DotNetNuke. At the end of this parsing process, the result is an ASCX file that becomes the real skin file, which is loaded into the Default.aspx at the runtime event of a page request. Anytime after parsing the skin for the first time, you may go in and look at the ASCX file with a text editor, and even modify and see immediate changes without doing a parse. As tempting as editing the ASCX file may be (especially if you're an ASP.NET developer and understand editing ASCX files), you really should not be doing that. This ASCX file is regenerated and is replaced each time a HTM skin file is re-parsed.We will also want to create our skins in a way that would be compatible with the future versions of DotNetNuke. Starting off with an HTM skin file puts us on the path to achieve this goal. Finishing Touches The next thing you will want to do is add more tokens and a little HTML to make yourself a little more proud of your DNN skin. To do this, go back to your HTM file and add two or three items from the list of tokens shown as follows: [LOGO][BANNER][SEARCH][LANGUAGE][CURRENTDATE][BREADCRUMB][USER][COPYRIGHT][TERMS][PRIVACY][DOTNETNUKE] For a complete list of all DotNetNuke tokens, please refer to the DotNetNuke Skinning Guide document by Shaun Walker. You candownload it from http://www.dotnetnuke.com/LinkClick.aspx?fileticket=2ptHepzmuFA%3d&tabid=478&mid=857. Now add in some HTML. You may want to add in a few <hr>(horizontal rule) or <br>(vertical break) tags to separate things out. When you make changes and want to see them, remember to go to the Admin menu and then to the Skins page and re-parse the skin, then go to the Home page to see the changes. Summary The title for this article was Creating Your First Skin and that's exactly what we did.There are many reasons why you couldn't or wouldn't use this skin for a live site. Ofcourse, any website needs a good design, and some graphics, but if you've managed a DNN site, before you know you'll need some more panes and some precise positioning.
Read more
  • 0
  • 0
  • 4838

article-image-blender-3d-interview-allan-brito
Packt
23 Oct 2009
8 min read
Save for later

Blender 3D: Interview with Allan Brito

Packt
23 Oct 2009
8 min read
Meeba Abraham: Hi Allan, thank you for talking to us today, why don’t you tell us a bit about yourself and your background; how did you start working with Blender? Allan Brito: Hi, and thanks for this opportunity to talk a bit about myself. Well, I’m a 29 year-old architect from Brazil. After my graduation, I started working on visualization projects, mostly on 3ds Max for a small studio here in Brazil. After two years I started teaching 3D modeling and animation and I fell in love with teaching. I still teach 3D animation and modeling at a College here. With the help of my teaching experience, I began writing manuals and tutorials about 3D animation. Eventually, I decided to write a book about Blender in Portuguese, and the book was a huge success in Brazil. Currently I`m working on the third edition of this book. With the book, I also needed a way to keep in touch with the readers and discuss about Blender and 3D related stuff. So I started a web site (www.allanbrito.com), where I regularly write short articles and tutorials about Blender and its comparison with other 3D packages. Today the web site has grown considerably, and I continue to update it with content on Blender and other 3D software tools. Meeba Abraham: How long have you been working with it? Allan Brito: My first contact with Blender 3D was in 2003. I was invited by a friend to check out a great open source software for 3D visualization. I was really impressed by Blender, its potential, and the lightweight of the software. Coming from a 3ds Max background, it was a bit hard to get used to the interface and the keyboard shortcuts, but after a few weeks I started getting used to it. After the learning process, I started to use Blender as the main tool for my projects. I can`t say that it was easy to use at first, but with time Blender simply grew on me and became my main tool for my projects. Meeba Abraham: Can you tell about some of the key features of Blender that makes it a viable option to other professional 3D software? Allan Brito: There are many features in Blender that other professional 3D suites do not have. For instance, the integrated Game Engine, which allows you to produce interactive animations, is just awesome! For 3D modeling, Blender has a sculpt module where artists can create 3D models only by sculpt geometry in a way similar to what sculpting tools such as ZBrush and MudBox provides. The node editor in Blender is also an incredible tool to create materials and for post-production. Post-production is a powerful tool in Blender. There is a sequencer editor that works like a video editor. You can cut, join, and post-process videos in the sequence editor. For instance, an animator can create a full animation without the need of any other software. Recently, the Big Buck Bunny project introduced some great tools for character animation in Blender, like better fur, a new and improved particle system, new and improved UV Mapping and much more. I strongly recommend a visit to www.blender.org to check out the full list of features, which is huge. Meeba Abraham: Why is Blender an important 3D application that an aspiring graphics artist should consider using? Allan Brito: I believe that Blender has a great set of features that can help a graphic artist create some impressive art work. Why Blender? I guess the best answer is; why not? All the features offered by other 3D animation software are also available in Blender, such as character animation, physics simulation, particle animation, and much more. And with Blender being a free software, you won’t have to get a single license and be bounded to only one workstation. Besides the features, I believe in the community nature of Blender. If you feel a tool or feature is missing, just make a suggestion to the community or make the feature yourself! Meeba Abraham: Over the years, Blender has grown in popularity. What, in your opinion, are some of the main reasons for this? Allan Brito: In the last few years Blender gained many features that only the so-called high-end and expansive 3D software had. This puts the spotlight right into Blender, and some old and experienced professionals are using Blender today, to take a look at these advanced features, and they like it. Besides the features, the Blender Foundation is doing a great job by supporting Blender and promoting it outside the community. They organize conferences and projects to show the potentials of Blender as a 3D animation package. The last open movie—Big Buck Bunny—supported by the community is a great example of that. Meeba Abraham: Since Blender is an open source 3D application, the Blender community plays an important role in its growth. Can you shed some light on the blender community? How have they helped to popularize Blender? Allan Brito: What can I say? The Blender community is great and has been supporting the development of Blender for a long time. The last open movie is a great example of what this community can do. Big Buck Bunny is a project mainly created by the Blender community. Artists could buy the DVD of the animation even before the project started. And when the animation was finished, all Blender users could buy a shiny DVD of the animation that contains tutorials and all source files of the animation. Now, what if Pixar gave away all the production files of their animations. And even of you don’t want to buy the DVD, you can still download all of the content for free from the project Web site, www.bigbuckbunny.org. This is a great example of the Blender community spirit and how much support Blender gets from around the world. Meeba Abraham: You have just authored a book on Blender; how did you find the experience? Is this the first book you’ve written? Allan Brito: Writing a book on Blender was quite a challenge for me. Even with the experience of writing tutorials and short articles about Blender, writing a book was not easy! But after a few weeks, I was able to write the chapters naturally and almost on schedule. The biggest challenge for me was to write about a subject that no one else had written about yet. In my first book “Blender 3D – Guia do Usuário” written in Brazilian Portuguese, the challenge was even bigger. When I started writing that book, there weren’t any updated documentation on Blender features. So I had to do a lot of research myself. With this book, the challenge again was to write about something that no one else has ever written. Even with a few short tutorials around, there weren`t any full set of procedures or tips for working with architectural visualization in Blender. The experience was great and I hope this is just the first book in a long series of books! I have a few ideas for writing more books about Blender and I’m already working on some of them. Meeba Abraham: How do you anticipate it will help the Blender community? Is it different to other Blender books? Allan Brito: I believe that a lot of users want to use Blender for architectural visualization but have only found tutorials and books on character modeling and animation. This book was written with architectural visualization in mind. So every example and Blender tool is described specifically with architectural examples. Meeba Abraham: You make regular contributions to www.BlenderNation.com, how did you get involved with the site and what does it offer to the community? Allan Brito: BlenderNation is the comprehensive Web site for Blender related news. So if anyone is curious about what`s going on in the Blender community, the first place to look after the Foundation Web site is BlenderNation. My involvement with BlenderNation began with my writing articles about Blender in Brazilian Portuguese for my own web site (www.allanbrito.com). A few months later, I was invited by Bart Veldhuizen to write a few tutorials and I guess they liked my work! After that I was writing articles for BlenderNation as a Contributor Editor. And I have to say that it`s really great to be a part of it, and keep the Blender community updated. The experience with BlenderNation and the books inspired me to start a new project called Blender 3D Architect (www.blender3darchitect.com) where I write articles on how to use Blender for architectural visualization along with tips and tutorials. Meeba Abraham: Thanks for your time and contributions!
Read more
  • 0
  • 0
  • 3825

article-image-business-blogging-technorati-state-blogosphere-2008
Packt
23 Oct 2009
4 min read
Save for later

Business Blogging On The Up - Technorati State of the Blogosphere 2008

Packt
23 Oct 2009
4 min read
The report also states that blogs are profitable, it says: The majority of bloggers we surveyed currently have advertising on their blogs. Among those with advertising, the mean annual investment in their blog is $1,800, but it’s paying off. The mean annual revenue is $6,000 with $75K+ in revenue for those with 100,000 or more unique visitors per month. It is interesting to note that the majority of bloggers now display advertising. One of the most encouraging statistics is that the proportion of people blogging about their jobs and on behalf of their business is now so high: About half of bloggers are professional bloggers — blogging is not necessarily their full-time job, but they blog about their industry or profession in an unofficial capacity. 12% of bloggers blog in an official capacity for their company. The amount of cross-over between the groups is also interesting. It shows that personal and business blogging can be successfully combined: More than half of professional and corporate bloggers are also personal bloggers. This could be on a separate blog, or they may blog about personal interests within their professional blog. Corporate bloggers: 69% are also personal bloggers 65% are professional bloggers Professional bloggers: 59% are also personal bloggers 17% are corporate bloggers It’s very encouraging to see the positive benefits being enjoyed by business and professional bloggers, with the majority of those surveyed reporting a positive impact as a result of their blog. Half of them say they are better known in their industry and a quarter see their blog as a useful résumé enhancement. Impact of blogging on professional life: Business bloggers also report that blogging has brought many unique opportunities that wouldn’t have otherwise been available. Taking part in an event, contributing to a print publication or even appearing on radio or TV are the kinds of things they are involved in, thanks to their blog. Have you been invited to any of the following as the result of your blog? Blogging is a time consuming activity. This is confirmed by the report which shows that a quarter of bloggers spend over 10 hours per week on their blog and nearly half spend 5 hours or more. Time spent blogging each week: As I mention in WordPress For Business Bloggers, many bloggers take on help to run their blog. This is particularly true for corporate or business bloggers, of whom nearly 20% have paid staff working for them. Blogs with higher Technorati authority are updated more frequently than those with less authority, as the report states: The Technorati Top 100 are prolific, with 43% posting ten times per day or more often. Only 8% post once a day or less frequently, compared to 13% of the next 500 bloggers, and 22% of the next 5000 bloggers. I highlight the importance of using tags in WordPress For Business Bloggers, and this is borne out by the data. Technorati top 100 bloggers are twice as likely to tag their posts. Percentage of bloggers who use tags: Promoting a blog well is key to its success and the report shows us the top traffic-building strategies used. These are particularly important for business bloggers, so all the techniques highlighted in the chart below are covered in WordPress For Business Bloggers, you’ll find many of them in Chapter 7, Supercharged Promotion: The vast majority of bloggers are tracking their site visitors and monthly page views, with Google Analytics being used by two thirds of them. Using Google Analytics with WordPress is covered in detail in the book, WordPress For Business Bloggers. Direct revenue generation is becoming an important aspect of blogging, with the majority of bloggers now displaying ads, affiliate marketing or other form of revenue generation (this subject is covered in detail in Chapter 10 of WordPress For Business Bloggers): The report data seems to suggest that the medium of blogging is gaining credibility and being taken more seriously as a source of information. 37% of bloggers have been quoted in the traditional media as a result of one of their posts. This is encouraging for business bloggers who use their blog as a PR tool. All in all, the State of the Blogosphere 2008 report makes encouraging reading for business bloggers as well as anyone who is thinking about starting a blog for their business. A blog can be a tremendously powerful tool for any business and using a top quality platform like WordPress makes running a blog extremely easy.  
Read more
  • 0
  • 0
  • 1466

article-image-class-less-objects-javascript
Packt
23 Oct 2009
7 min read
Save for later

Class-less Objects in JavaScript

Packt
23 Oct 2009
7 min read
JavaScript Objects When you think about a JavaScript object, think a hash. That's all there is to objects - they are just collections of name-value pairs, where the values can be anything including other objects and functions. When an object's property is a function, you can also call it a method. This is an empty object: var myobj = {}; Now you can start adding some meaningful functionality to this object: myobj.name = "My precious";myobj.getName = function() {return this.name}; Note a few things here: this inside a method refers to the current object, as expected you can add/tweak/remove properties at any time, not only during creation Another way to create an object and add properties/methods to it at the same time, is like this: var another = { name: 'My other precious', getName: function() { return this.name; }}; This syntax is the so-called object literal notation - you wrap everything in curly braces { and } and separate the properties inside the object with a comma. Key:value pairs are separated by colons. This syntax is not the only way to create objects though. Constructor Functions Another way to create a JavaScript object is by using a constructor function. Here's an example of a constructor function: function ShinyObject(name) { this.name = name; this.getName = function() { return this.name; }} Now creating an object is much more Java-like: var my = new ShinyObject('ring');var myname = my.getName(); // "ring" There is no difference in the syntax for creating a constructor function as opposed to any other function, the difference is in the usage. If you invoke a function with new, it creates and returns an object and, via this, you have access to modifying the object before you return it. By convention though, constructor functions are named with a capital letter to distinguish visually from normal functions and methods. So which way is better - object literal or constructor function? Well, that depends on your specific task. For example, if you need to create many different, yet similar objects, then the class-like constructors may be the right choice. But if your object is more of a one-off singleton, then object literal is definitely simpler and shorter. OK then, so since there are no classes, how about inheritance? Before we get there, here comes a little surprise - in JavaScript, functions are actually objects. (Actually in JavaScript pretty much everything is an object, with the exception of the few primitive data types - string, boolean, number and undefined. Functions are objects, arrays are objects, even null is an object. Furthermore, the primitive data types can also be converted and used as objects, so for example "string".length is valid.) Function Objects and Prototype Property In JavaScript, functions are objects. They can be assigned to variables, you can add properties and methods to them and so on. Here's an example of a function: var myfunc = function(param) { alert(param);}; This is pretty much the same as: function myfunc(param) { alertparam);} No matter how you create the function, you end up with a myfunc object and you can access its properties and methods. alert(myfunc.length); // alerts 1, the number of parametersalert(myfunc.toString()); // alerts the source code of the function One of the interesting properties that every function object has is the prototype property. As soon as you create a function, it automatically gets a prototype property which points to an empty object. Of course, you can modify the properties of that empty object. alert(typeof myfunc.prototype); // alerts "object"myfunc.prototype.test = 1; // completely OK to do so The question is, how is this prototype thing useful? It's used only when you invoke a function as a constructor to create objects. When you do so, the objects automatically get a secret link to the prototype's properties and can access them as their own properties. Confusing? Let's see an example. A new function: function ShinyObject(name) { this.name = name;} Augmenting the prototype property of the function with some functionality: ShinyObject.prototype.getName = function() { return this.name;}; Using the function as a constructor function to create an object: var iphone = new ShinyObject('my precious');iphone.getName(); // returns "my precious" As you can see the new objects automatically get access to the prototype's properties. And when something is getting functionality "for free", this starts to smell like code reusability and inheritance.   Inheritance via Prototype Now let's see how you can use the prototype to implement inheritance. Here's a constructor function which will be the parent: function NormalObject() { this.name = 'normal'; this.getName = function() { return this.name; };} Now a second constructor: function PreciousObject(){ this.shiny = true; this.round = true;} Now the inheritance part: PreciousObject.prototype = new NormalObject(); Voila! Now you can create precious objects and they'll get all the functionality of the normal objects: var crystal_ball = new PreciousObject();crystal_ball.name = 'Ball, Crystal Ball.';alert(crystal_ball.round); // truealert(crystal_ball.getName()); // "Ball, Crystal Ball." Notice how we needed to create an object with new and assign it to the prototype, because the prototype is just an object. It's not like one constructor function inherited from another, in essence we inherited from an object. JavaScript doesn't have classes that inherit from other classes, here objects inherit from other objects. If you have several constructor functions that will inherit NormalObject objects, you may create new NormalObject() every time, but it's not necessary. Even the whole NormalObject constructor may not be needed. Another way to do the same would be to create one (singleton) normal object and use it as a base for the other objects. var normal = { name: 'normal', getName: function() { return this.name; }}; Then the PreciousObject can inherit like this: PreciousObject.prototype = normal; Inheritance by Copying Properties Since inheritance is all about reusing code, yet another way to implement it is to simply copy properties. Imagine you have these objects: var shiny = { shiny: true, round: true};var normal = { name: 'name me', getName: function() { return this.name; }}; How can shiny get normal's properties? Here's a simple extend() function that loops through and copies properties: function extend(parent, child) { for (var i in parent) { child[i] = parent[i]; }}extend(normal, shiny); // inheritshiny.getName(); // "name me" Now this property copying may look like overhead and not performing too well, but truth is, for many tasks it's just fine. You can also see that this is an easy way to implement mixins and multiple inheritance. Crockford's beget Object Douglas Crockford, a JavaScript guru and creator of JSON, suggests this interesting begetObject() way of implementing inheritance: function begetObject(o) { function F() {} F.prototype = o; return new F();} Here you create a temp constructor so you can use the prototype functionality, the idea is that you create a new object, but instead of starting fresh, you inherit some functionality from another, already existing, object. Parent object: var normal = { name: 'name me', getName: function() { return this.name; }}; A new object inheriting from the parent: var shiny = begetObject(normal); Augment the new object with more functionality: shiny.round = true;shiny.preciousness = true; YUI's extend() Let's wrap up with yet another way to implement inheritance, which is probably the closest to Java, because in this method, it looks like a constructor function inherits from another constructor function, hence it looks a bit like a class inheriting from a class. This method is used in the popular YUI JavaScript library (Yahoo! User Interface) and here's a little simplified version: function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F();} With this method you pass two constructor functions and the first (the child) gets all the properties and methods of the second (the parent) via the prototype property. Summary Let's quickly summarize what we just learned about JavaScript: there are no classes objects inherit from objects object literal notation var o = {}; constructor functions provide Java-like syntax var o = new Object(); functions are objects all function objects have a prototype property And finally, there are dozens of ways to implement inheritance, you can pick and choose depending on your task at hand, personal preferences, team preferences, mood or the current phase of the Moon.  
Read more
  • 0
  • 0
  • 2601

article-image-automation-python-and-stafstax
Packt
23 Oct 2009
13 min read
Save for later

Automation with Python and STAF/STAX

Packt
23 Oct 2009
13 min read
The reader should note that the solution is only intended to explain how Python and STAF may be used. No claim is made that the solution presented here is the best one in any way, just that is one more option that the reader may consider in future developments. The Problem Let's imagine that we have a computer network in which a machine periodically generates some kind of file with information that is of interest to other machines in that network. For example, let's say that this file is a new software build of a product that must transferred to a group of remote machines, in which its functionality has to be tested to make sure it can be delivered to the client. The Python-only solution Sequential A simple solution to make the software build available to all the testing machines could be to copy it to a specific directory whenever a new file is available. For additional security, let's suppose that we're required to verify that the md5 sum for both original and destination files is equal to ensure that build file was copied correctly. If it is considered that /tmp is a good destination directory, then the following script will do the job: 1 #!/usr/bin/python 2 """ 3 Copy a given file to a list of destination machines sequentially 4 """ 5 6 import os, argparse 7 import subprocess 8 import logging 9 10 def main(args): 11 logging.basicConfig(level=logging.INFO, format="%(message)s") 12 13 # Calculate md5 sum before copyin the file 14 orig_md5 = run_command("md5sum %s" % args.file).split()[0] 15 16 # Copy the file to every requested machine and verify 17 # that md5 sum of the destination file is equal 18 # to the md5 sum of the original file 19 for machine in args.machines: 20 run_command("scp %s %s:/tmp/" % (args.file, machine)) 21 dest_md5 = run_command("ssh %s md5sum /tmp/%s" 22 % (machine, os.path.basename(args.file))).split()[0] 23 assert orig_md5 == dest_md5 24 25 def run_command(command_str): 26 """ 27 Run a given command and another process and return stdout 28 """ 29 logging.info(command_str) 30 return subprocess.Popen(command_str, stdout=subprocess.PIPE, 31 shell=True).communicate()[0] 32 33 if __name__ == "__main__": 34 parser = argparse.ArgumentParser(description=__doc__) 35 parser.add_argument("file", 36 help="File to copy") 37 parser.add_argument(metavar="machine", dest="machines", nargs="+", 38 help="List of machines to which file must be copied") 39 40 args = parser.parse_args() 41 args.file = os.path.realpath(args.file) 42 main(args) Here it is assumed that ssh keys have been exchanged between origin and destination machines for automatic authentication without human intervention. The script makes use of the Popen class in the subprocess python standard library. This powerful library provides the capability to launch new operating system processes and capture not only the result code, but also the standard output and error streams. However, it should be taken into account that the Popen class cannot be used to invoke commands on a remote machine by itself. However, as it can be seen in the code, ssh and related commands may be used to launch processes on remote machines when configured properly. For example, if the file of interest was STAF325-src.tar.gz (STAF 3.2.5 source) and the remote machines were 192.168.1.1 and 192.168.1.2, then the file would be copied using the copy.py script in the following way: $ ./copy.py STAF325-src.tar.gz 192.168.1.{1,2}md5sum STAF325-src.tar.gzscp STAF325-src.tar.gz 192.168.1.1:/tmp/ssh 192.168.1.1 md5sum /tmp/STAF325-src.tar.gzscp STAF325-src.tar.gz 192.168.1.2:/tmp/ssh 192.168.1.2 md5sum /tmp/STAF325-src.tar.gz Parallel What would happen if the files were copied in parallel? For this example, it might not make much sense given that probably the network is at bottleneck and there isn't any increase in performance. However, in the case of the md5sum operation, it's a waste of time waiting for the operation to complete on one machine while the other is essentially idle waiting for the next command. Clearly, it would be more interesting to make both machines do the job in parallel to take advantage of CPU cycles. A parallel implementation similar to the sequential one is displayed below: 1 #!/usr/bin/python 2 """ 3 Copy a given file to a list of destination machines in parallel 4 """ 5 6 import os, argparse 7 import subprocess 8 import logging 9 import threading 10 11 def main(args): 12 logging.basicConfig(level=logging.INFO, format="%(threadName)s: %(message)s") 13 orig_md5 = run_command("md5sum %s" % args.file).split()[0] 14 15 # Create one thread for machine 16 threads = [ WorkingThread(machine, args.file, orig_md5) 17 for machine in args.machines] 18 19 # Run all threads 20 for thread in threads: 21 thread.start() 22 23 # Wait for all threads to finish 24 for thread in threads: 25 thread.join() 26 27 class WorkingThread(threading.Thread): 28 """ 29 Thread that performs the copy operation for one machine 30 """ 31 def __init__(self, machine, orig_file, orig_md5): 32 threading.Thread.__init__(self) 33 34 self.machine = machine 35 self.file = orig_file 36 self.orig_md5 = orig_md5 37 38 def run(self): 39 # Copy file to remote machine 40 run_command("scp %s %s:/tmp/" % (self.file, self.machine)) 41 42 # Calculate md5 sum of the file copied at the remote machine 43 dest_md5 = run_command("ssh %s md5sum /tmp/%s" 44 % (self.machine, os.path.basename(self.file))).split()[0] 45 assert self.orig_md5 == dest_md5 46 47 def run_command(command_str): 48 """ 49 Run a given command and another process and return stdout 50 """ 51 logging.info(command_str) 52 return subprocess.Popen(command_str, stdout=subprocess.PIPE, 53 shell=True).communicate()[0] 54 55 if __name__ == "__main__": 56 parser = argparse.ArgumentParser(description=__doc__) 57 parser.add_argument("file", 58 help="File to copy") 59 parser.add_argument(metavar="machine", dest="machines", nargs="+", 60 help="List of machines to which file must be copied") 61 62 args = parser.parse_args() 63 args.file = os.path.realpath(args.file) 64 main(args) Here the same assumptions as in the sequential case are made. In this solution the work that was done inside the for loop is now implemented in the run method of a class that is inherited from threading.Thread class, which is a class that provides an easy way to create working threads such as the ones in the example. In this case, the output of the command, using the same arguments as in the previous example, is: $ ./copy_parallel.py STAF325-src.tar.gz 192.168.1.{1,2}MainThread: md5sum STAF325-src.tar.gzThread-1: scp STAF325-src.tar.gz 192.168.1.1:/tmp/Thread-2: scp STAF325-src.tar.gz 192.168.1.2:/tmp/Thread-2: ssh 192.168.1.2 md5sum /tmp/STAF325-src.tar.gzThread-1: ssh 192.168.1.1 md5sum /tmp/STAF325-src.tar.gz As it can be seen in the logs, md5sum command execution isn't necessarily executed in the same order as threads were created. This solution isn't much more complex than the sequential one, but it finishes earlier. Hence, in the case in which a CPU intensive task must be performed in every machine, the parallel solution will be more convenient since the small increment in coding complex will pay off in execution performance. The Python+STAF solution Sequential The solutions to the problem presented in the previous section are perfectly fine. However, some developers may find it cumbersome to write scripts from scratch using Popen class and desire to work with a platform with feature such as launching process on remote machines already implemented. That's were STAF (Software Testing Automation Framework) might be helpful. STAF is a framework that provides the ability to automate jobs specially, but not uniquely, for testing environments. STAF is implemented as a process which runs on every machine that provides services that may be used by clients to accomplish different tasks. For more information regarding STAF, please refer to the project homepage. The Python+STAF sequential version of the program that has been used as example throughout this article is below: 1 #!/usr/bin/python 2 """ 3 Copy a given file to a list of destination machines sequentially 4 """ 5 6 import os, argparse 7 import subprocess 8 import logging 9 import PySTAF 10 11 def main(args): 12 logging.basicConfig(level=logging.INFO, format="%(message)s") 13 handle = PySTAF.STAFHandle(__file__) 14 15 # Calculate md5 sum before copyin the file 16 orig_md5 = run_process_command(handle, "local", "md5sum %s" % args.file).split()[0] 17 18 # Copy the file to every requested machine and verify 19 # that md5 sum of the destination file is equal 20 # to the md5 sum of the original file 21 for machine in args.machines: 22 copy_file(handle, args.file, machine) 23 dest_md5 = run_process_command(handle, machine, "md5sum /tmp/%s" 24 % os.path.basename(args.file)).split()[0] 25 assert orig_md5 == dest_md5 26 27 handle.unregister() 28 29 def run_process_command(handle, location, command_str): 30 """ 31 Run a given command and another process and return stdout 32 """ 33 logging.info(command_str) 34 35 result = handle.submit(location, "PROCESS", "START SHELL COMMAND %s WAIT RETURNSTDOUT" 36 % PySTAF.STAFWrapData(command_str)) 37 assert result.rc == PySTAF.STAFResult.Ok 38 39 mc = PySTAF.unmarshall(result.result) 40 return mc.getRootObject()['fileList'][0]['data'] 41 42 def copy_file(handle, filename, destination): 43 """ 44 Run a given command and another process and return stdout 45 """ 46 logging.info("copying %s to %s" % (filename, destination)) 47 48 result = handle.submit("local", "FS", "COPY FILE %s TODIRECTORY /tmp TOMACHINE %s" 49 % (PySTAF.STAFWrapData(filename), 50 PySTAF.STAFWrapData(destination))) 51 assert result.rc == PySTAF.STAFResult.Ok 52 53 if __name__ == "__main__": 54 parser = argparse.ArgumentParser(description=__doc__) 55 parser.add_argument("file", 56 help="File to copy") 57 parser.add_argument(metavar="machine", dest="machines", nargs="+", 58 help="List of machines to which file must be copied") 59 60 args = parser.parse_args() 61 args.file = os.path.realpath(args.file) 62 main(args) The code makes use of PySTAF, a python library, which is shipped with the STAF software that provides the ability to interact with the framework as a client. The typical usage of the library may summarized as follows: Register a handle in STAF (line 13): The communication with the server process is managed using handles. A client must have a handle to be able to send requests to local and/or remote machines. Submit requests (lines 35 and 48): Once the handle is available at the client, the client can use it to submit requests to any location and service. The two basic services that are used in this example are PROCESS, which is used to launch processes on a machine the same way ssh was used in the python-only version of the example; and FS, which is used to copy files between different machines as scp was used in the python-only solution. Check result code (lines 37 and 51): After a request has been submitted, result code should be checked to make sure that there wasn't any communication or syntax problem. Unmarshall results (lines 39-40): When the standard output is captured, it must be unmarshalled before using it in python since responses are encoded in a language independent format. Unregister handle (line 27): When STAF isn't needed anymore, it's advisable to unregister the handle to free resources allocated to the client in the server. Compared with the python-only solution, the advantages of STAF aren't appreciable at first sight. The handler syntax isn't easier than creating Popen objects and we have to deal with marshalling when we previously were just parsing text. However, as a framework, if has to be taken into account that it is has a learning curve and has much more functionality to offer than this one that makes it worthwhile. Please bear with me until section 5, in which the STAX solution we'll be shown, with an example with a completely different approach to the problem. Using the script in this section, the output would be pretty much the same as the previous sequential example: $ ./staf_copy.py STAF325-src.tar.gz 192.168.1.{1,2}md5sum STAF325-src.tar.gzcopying STAF325-src.tar.gz to 192.168.1.1md5sum /tmp/STAF325-src.tar.gzcopying STAF325-src.tar.gz to 192.168.1.2md5sum /tmp/STAF325-src.tar.gz As in the previous section, the sequential solution suffers the same problems when CPU intensive tasks are to be performed. Hence, the same comments apply. Parallel When using STAF, the parallel solution requires the same changes that were explained before. That is, create a new class that inherits from threading.Thread and implement the working threads. The code below shows how this might be implemented: 1 #!/usr/bin/python 2 """ 3 Copy a given file to a list of destination machines in parallel 4 """ 5 6 import os, argparse 7 import subprocess 8 import logging 9 import threading 10 import PySTAF 11 12 def main(args): 13 logging.basicConfig(level=logging.INFO, format="%(threadName)s %(message)s") 14 handle = PySTAF.STAFHandle(__file__) 15 orig_md5 = run_process_command(handle, "local", "md5sum %s" % args.file).split()[0] 16 17 # Create one thread for machine 18 threads = [ WorkingThread(machine, args.file, orig_md5) 19 for machine in args.machines] 20 21 # Run all threads 22 for thread in threads: 23 thread.start() 24 25 # Wait for all threads to finish 26 for thread in threads: 27 thread.join() 28 29 handle.unregister() 30 31 class WorkingThread(threading.Thread): 32 """ 33 Thread that performs the copy operation for one machine 34 """ 35 def __init__(self, machine, orig_file, orig_md5): 36 threading.Thread.__init__(self) 37 38 self.machine = machine 39 self.file = orig_file 40 self.orig_md5 = orig_md5 41 self.handle = PySTAF.STAFHandle("%s:%s" % (__file__, self.getName())) 42 43 def run(self): 44 # Copy file to remote machine 45 copy_file(self.handle, self.file, self.machine) 46 47 # Calculate md5 sum of the file copied at the remote machine 48 dest_md5 = run_process_command(self.handle, self.machine, "md5sum /tmp/%s" 49 % os.path.basename(self.file)).split()[0] 50 assert self.orig_md5 == dest_md5 51 self.handle.unregister() 52 53 def run_process_command(handle, location, command_str): 54 """ 55 Run a given command and another process and return stdout 56 """ 57 logging.info(command_str) 58 59 result = handle.submit(location, "PROCESS", "START SHELL COMMAND %s WAIT RETURNSTDOUT" 60 % PySTAF.STAFWrapData(command_str)) 61 assert result.rc == PySTAF.STAFResult.Ok 62 63 mc = PySTAF.unmarshall(result.result) 64 return mc.getRootObject()['fileList'][0]['data'] 65 66 def copy_file(handle, filename, destination): 67 """ 68 Run a given command and another process and return stdout 69 """ 70 logging.info("copying %s to %s" % (filename, destination)) 71 72 result = handle.submit("local", "FS", "COPY FILE %s TODIRECTORY /tmp TOMACHINE %s" 73 % (PySTAF.STAFWrapData(filename), 74 PySTAF.STAFWrapData(destination))) 75 assert result.rc == PySTAF.STAFResult.Ok 76 77 if __name__ == "__main__": 78 parser = argparse.ArgumentParser(description=__doc__) 79 parser.add_argument("file", 80 help="File to copy") 81 parser.add_argument(metavar="machine", dest="machines", nargs="+", 82 help="List of machines to which file must be copied") 83 84 args = parser.parse_args() 85 args.file = os.path.realpath(args.file) 86 main(args) As it happened before, this solution is faster since it takes advantage of having multiple CPUs working on md5sum calculation instead of just one at a time. The output we get invoking the script could be: $ ./staf_copy_parallel.py STAF325-src.tar.gz 192.168.1.{1,2}MainThread md5sum STAF325-src.tar.gzThread-1 copying STAF325-src.tar.gz to 192.168.1.1Thread-2 copying STAF325-src.tar.gz to 192.168.1.2Thread-2 md5sum /tmp/STAF325-src.tar.gzThread-1 md5sum /tmp/STAF325-src.tar.gz This time it can be seen that md5sum calculation mustn't necessarily start in the same order as file copy operation. Once again, this solution is slightly more complex, but the gain in performance makes it convenient when dealing with tasks with high computational cost.    
Read more
  • 0
  • 0
  • 7581

article-image-troubleshooting-lotus-notesdomino-7-applications
Packt
23 Oct 2009
19 min read
Save for later

Troubleshooting Lotus Notes/Domino 7 applications

Packt
23 Oct 2009
19 min read
Introduction The major topics that we'll cover in this article are: Testing your application (in other words, uncovering problems before your users do it for you). Asking the right questions when users do discover problems. Using logging to help troubleshoot your problems. We'll also examine two important new Notes/Domino 7 features that can be critical for troubleshooting applications: Domino Domain Monitoring (DDM) Agent Profiler   For more troubleshooting issues visit: TroubleshootingWiki.org Testing your Application Testing an application before you roll it out to your users may sound like an obvious thing to do. However, during the life cycle of a project, testing is often not allocated adequate time or money. Proper testing should include the following: A meaningful amount of developer testing and bug fixing: This allows you to catch most errors, which saves time and frustration for your user community. User representative testing: A user representative, who is knowledgeable about the application and how users use it, can often provide more robust testing than the developer. This also provides early feedback on features. Pilot testing: In this phase, the product is assumed to be complete, and a pilot group uses it in production mode. This allows for limited stress testing as well as more thorough testing of the feature set. In addition to feature testing, you should test the performance of the application. This is the most frequently skipped type of testing, because some consider it too complex and difficult. In fact, it can be difficult to test user load, but in general, it's not difficult to test data load. So, as part of any significant project, it is a good practice to programmatically create the projected number of documents that will exist within the application, one or two years after it has been fully deployed, and have a scheduled agent trigger the appropriate number of edits-per-hour during the early phases of feature testing. Although this will not give a perfect picture of performance, it will certainly help ascertain whether and why the time to create a new document is unacceptable (for example, because the @Db formulas are taking too long, or because the scheduled agent that runs every 15 minutes takes too long due to slow document searches). Asking the Right Questions Suppose that you've rolled out your application and people are using it. Then the support desk starts getting calls about a certain problem. Maybe your boss is getting an earful at meetings about sluggish performance or is hearing gripes about error messages whenever users try to click a button to perform some action. In this section, we will discuss a methodology to help you troubleshoot a problem when you don't necessarily have all the information at your disposal. We will include some specific questions that can be asked verbatim for virtually any application. The first key to success in troubleshooting an application problem is to narrow down where and when it happens. Let's take these two very different problems suggested above (slow performance and error messages), and pose questions that might help unravel them: Does the problem occur when you take a specific action? If so, what is that action? Your users might say, "It's slow whenever I open the application", or "I get an error when I click this particular button in this particular form". Does the problem occur for everyone who does this, or just for certain people? If just certain people, what do they have in common? This is a great way to get your users to help you help them. Let them be a part of the solution, not just "messengers of doom". For example, you might ask questions such as, "Is it slow only for people in your building or your floor? Is it slow only for people accessing the application remotely? Is it slow only for people who have your particular access (for example, SalesRep)?" Does this problem occur all the time, at random times, or only at certain times? It's helpful to check whether or not the time of day or the day of week/month is relevant. So typical questions might be similar to the following: "Do you get this error every time you click the button or just sometimes? If just sometimes, does it give you the error during the middle of the day, but not if you click it at 7 AM when you first arrive? Do you only get the error on Mondays or some other day of the week? Do you only see the error if the document is in a certain status or has certain data in it? If it just happens for a particular document, please send me a link to that document so that I can inspect it carefully to see if there is invalid or unexpected data." Logging Ideally, your questions have narrowed down the type of problem it could be. So at this point, the more technical troubleshooting can start. You will likely need to gather concrete information to confirm or refine what you're hearing from the users. For example, you could put a bit of debugging code into the button that they're clicking so that it gives more informative errors, or sends you an email (or creates a log document) whenever it's clicked or whenever an error occurs. Collecting the following pieces of information might be enough to diagnose the problem very quickly: Time/date User name Document UNID (if the button is pushed in a document) Error Status or any other likely field that might affect your code By looking for common denominators (such as the status of the documents in question, or access or roles of the users), you will likely be able to further narrow down the possibilities of why the problem is happening. This doesn't solve your problem of course, but it helps in advancing you a long way towards that goal. A trickier problem to troubleshoot might be one we mentioned earlier: slow performance. Typically, after you've determined that there is some kind of performance delay, it's a good idea to first collect some server logging data. Set the following Notes.ini variables in the Server Configuration document in your Domino Directory, on the Notes.ini tab: Log_Update=1Log_AgentManager=1 These variables instruct the server to write output to the log.nsf database in the Miscellaneous Events view. Note that they may already be set in your environment. If not, they're fairly unobtrusive, and shouldn't trouble your administration group. Set them for a 24-hour period during a normal business week, and then examine the results to see if anything pops out as being suspicious. For view indexing, you should look for lines like these in the Miscellaneous Events (Log_Update=1): 07/01/2006 09:29:57 AM Updating views in appsSalesPipeline.nsf07/01/2006 09:30:17 AM Finished updating views in appsSalesPipeline.nsf07/01/2006 09:30:17 AM Updating views in appsTracking.nsf07/01/2006 09:30:17 AM Finished updating views in appsTracking.nsf07/01/2006 09:30:17 AM Updating views in appsZooSchedule.nsf07/01/2006 09:30:18 AM Finished updating views in appsZooSchedule.nsf And lines like these for Agent execution (Log_AgentManager=1): 06/30/2006 09:43:49 PM AMgr: Start executing agent 'UpdateTickets' in 'appsSalesPipeline.nsf ' by Executive '1'06/30/2006 09:43:52 PM AMgr: Start executing agent 'ZooUpdate' in 'appsZooSchedule.nsf ' by Executive '2'06/30/2006 09:44:44 PM AMgr: Start executing agent 'DirSynch' in 'appsTracking.nsf ' by Executive '1' Let's examine these lines to see whether or not there is anything we can glean from them. Starting with the Log_Update=1 setting, we see that it gives us the start and stop times for every database that gets indexed. We also see that the database file paths appear alphabetically. This means that, if we search for the text string updating views and pull out all these lines covering (for instance) an hour during a busy part of the day, and copy/paste these lines into a text editor so that they're all together, then we should see complete database indexing from A to Z on your server repeating every so often. In the log.nsf database, there may be many thousands of lines that have nothing to do with your investigation, so culling the important lines is imperative for you to be able to make any sense of what's going on in your environment. You will likely see dozens or even hundreds of databases referenced. If you have hundreds of active databases on your server, then culling all these lines might be impractical, even programmatically. Instead, you might focus on the largest group of databases. You will notice that the same databases are referenced every so often. This is the Update Cycle, or view indexing cycle. It's important to get a sense of how long this cycle takes, so make sure you don't miss any references to your group of databases. Imagine that SalesPipeline.nsf and Tracking.nsf were the two databases that you wanted to focus on. You might cull the lines out of the log that have updating views and which reference these two databases, and come up with something like the following: 07/01/2006 09:29:57 AM Updating views in appsSalesPipeline.nsf07/01/2006 09:30:17 AM Finished updating views in appsSalesPipeline.nsf07/01/2006 09:30:17 AM Updating views in appsTracking.nsf07/01/2006 09:30:20 AM Finished updating views in appsTracking.nsf07/01/2006 10:15:55 AM Updating views in appsSalesPipeline.nsf07/01/2006 10:16:33 AM Finished updating views in appsSalesPipeline.nsf07/01/2006 10:16:33 AM Updating views in appsTracking.nsf07/01/2006 10:16:43 AM Finished updating views in appsTracking.nsf07/01/2006 11:22:31 AM Updating views in appsSalesPipeline.nsf07/01/2006 11:23:33 AM Finished updating views in appsSalesPipeline.nsf07/01/2006 11:23:33 AM Updating views in appsTracking.nsf07/01/2006 11:23:44 AM Finished updating views in appsTracking.nsf This gives us some very important information: the Update task (view indexing) is taking approximately an hour to cycle through the databases on the server; that's too long. The Update task is supposed to run every 15 minutes, and ideally should only run for a few minutes each time it executes. If the cycle is an hour, then that means update is running full tilt for that hour, and as soon as it stops, it realizes that it's overdue and kicks off again. It's possible that if you examine each line in the log, you'll find that certain databases are taking the bulk of the time, in which case it might be worth examining the design of those databases. But it might be that every database seems to take a long time, which might be more indicative of a general server slowdown. In any case, we haven't solved the problem; but at least we know that the problem is probably server-wide. More complex applications, and newer applications, tend to reflect server‑performance problems more readily, but that doesn't necessarily mean they carry more responsibility for the problem. In a sense, they are the "canary in the coal mine". If you suspect the problem is confined to one database (or a few), then you can increase the logging detail by setting Log_Update=2. This will give you the start time for every view in every database that the Update task indexes. If you see particular views taking a long time, then you can examine the design of those views. If no database(s) stand out, then you might want to see if the constant indexing occurs around the clock or just during business hours. If it's around the clock, then this might point to some large quantities of data that are changing in your databases. For example, you may be programmatically synchronizing many gigabytes of data throughout the day, not realizing the cost this brings in terms of indexing. If slow indexing only occurs during business hours, then perhaps the user/data load has not been planned out well for this server. As the community of users ramps up in the morning, the server starts falling behind and never catches up until evening. There are server statistics that can help you determine whether or not this is the case. (These server statistics go beyond the scope of this book, but you can begin your investigation by searching on the various Notes/Domino forums for "server AND performance AND statistics".) As may be obvious at this point, troubleshooting can be quite time-consuming. The key is to make sure that you think through each step so that it either eliminates something important, or gives you a forward path. Otherwise, you can find yourself still gathering information weeks and months later, with users and management feeling very frustrated. Before moving on from this section, let's take a quick look at agent logging. Agent Manager can run multiple agents in different databases, as determined by settings in your server document. Typically, production servers only allow two or three concurrent agents to run during business hours, and these are marked in the log as Executive '1', Executive '2', and so on. If your server is often busy with agent execution, then you can track Executive '1' and see how many different agents it runs, and for how long. If there are big gaps between when one agent starts and when the next one does (for Executive '1'), this might raise suspicion that the first agent took that whole time to execute. To verify this, turn up the logging by setting the Notes.ini variable debug_amgr=*. (This will output a fair amount of information into your log, so it's best not to leave it on for too long, but normally one day is not a problem.) Doing this will give you a very important piece of information: the number of "ticks" it took for the agent to run. One second equals 100 ticks, so if the agent takes 246,379 ticks, this equals 2,463 seconds (about 41 minutes). As a general rule, you want scheduled agents to run in seconds, not minutes; so any agent that is taking this long will require some examination. In the next section, we will talk about some other ways you can identify problematic agents. Domino Domain Monitoring (DDM) Every once in a while, a killer feature is introduced—a feature so good, so important, so helpful, that after using it, we just shake our heads and wonder how we ever managed without it for so long. Domino Domain Monitor (DDM) is just such a feature. DDM is too large to be completely covered in this one section, so we will confine our overview to what it can do in terms of troubleshooting applications. For a more thorough explanation of DDM and all its features, see the book, Upgrading to Lotus Notes and Domino (www.packtpub.com/upgrading_lotus/book). In the events4.nsf database, you will find a new group of documents you can create for tracking agent or application performance. On Domino 7 servers, a new database is created automatically with the filename ddm.nsf. This stores the DDM output you will examine. For application troubleshooting, some of the most helpful areas to track using DDM are the following: Full-text index needs to be built. If you have agents that are creating a full‑text index on the fly because the database has no full‑text index built, DDM can track that potential problem for you. Especially useful is the fact that DDM compiles the frequency per database, so (for instance) you can see if it happens once per month or once per hour. Creating full‑text indexes on the fly can result in a significant demand on server resources, so having this notification is very useful. We discuss an example of this later in this section. Agent security warnings. You can manually examine the log to try to find errors about agents not being able to execute due to insufficient access. However, DDM will do this for you, making it much easier to find (and therefore fix) such problems. Resource utilization. You can track memory, CPU, and time utilization of your agents as run by Agent Manager or by the HTTP task. This means that at any time you can open the ddm.nsf database and spot the worst offenders in these categories, over your entire server/domain. We will discuss an example of CPU usage later in this section. The following illustration shows the new set of DDM views in the events4.nsf (Monitoring configuration) database: The following screenshot displays the By Probe Server view after we've made a few document edits: Notice that there are many probes included out-of-the-box (identified by the property "author = Lotus Notes Template Development") but set to disabled. In this view, there are three that have been enabled (ones with checkmarks) and were created by one of the authors of this book. If you edit the probe document highlighted above, Default Application Code/Agents Evaluated By CPU Usage (Agent Manager), the document consists of three sections. The first section is where you choose the type of probe (in this case Application Code) and the subtype (in this case Agents Evaluated By CPU Usage). The second section allows you to choose the servers to run against, and whether you want this probe to run against agents/code executed by Agent Manager or by the HTTP task (as shown in the following screenshot). This is an important distinction. For one thing, they are different tasks, and therefore one can hit a limit while the other still has room to "breathe". But perhaps more significantly, if you choose a subtype of Agents Evaluated By Memory Usage, then the algorithms used to evaluate whether or not an agent is using too much memory are very different. Agents run by the HTTP task will be judged much more harshly than those run by the Agent Manager task. This is because with the HTTP task, it is possible to run the same agent with up to hundreds of thousands of concurrent executions. But with Agent Manager, you are effectively limited to ten concurrent instances, and none within the same database. The third section allows you to set your threshold for when DDM should report the activity: You can select up to four levels of warning: Fatal, Failure, Warning (High), and Warning (Low). Note that you do not have the ability to change the severity labels (which appear as icons in the view). Unless you change the database design of ddm.nsf, the icons displayed in the view and documents are non-configurable. Experiment with these settings until you find the approach that is most useful for your corporation. Typically, customers start by overwhelming themselves with information, and then fine-tuning the probes so that much less information is reported. In this example, only two statuses are enabled: one for six seconds, with a label of Warning (High), and one for 60 seconds, with a label of Failure. Here is a screenshot of the DDM database: Notice that there are two Application Code results, one with a status of Failure (because that agent ran for more than 60 seconds), and one with a status of Warning (High) (because that agent ran for more than six seconds but less than 60 seconds). These are the parameters set in the Probe document shown previously, which can easily be changed by editing that Probe document. If you want these labels to be different, you must enable different rows in the Probe document. If you open one of these documents, there are three sections. The top section gives header information about this event, such as the server name, the database and agent name, and so on. The second section includes the following table, with a tab for the most recent infraction and a tab for previous infractions. This allows you to see how often the problem is occurring, and with what severity. The third section provides some possible solutions, and (if applicable) automation. For example, in our example, you might want to "profile" your agent. (We will profile one of our agents in the final section of this article.) DDM can capture full-text operations against a database that is not full‑text indexed. It tracks the number of times this happens, so you can decide whether to full‑text index the database, change the agent, or neither. For a more complete list of the errors and problems that DDM can help resolve, check the Domino 7 online help or the product documentation (www.lotus.com). Agent Profiler If any of the troubleshooting tips or techniques we've discussed in this article causes you to look at an agent and think, "I wonder what makes this agent so slow", then the Agent Profiler should be the next tool to consider. Agent Profiler is another new feature introduced in Notes/Domino 7. It gives you a breakdown of many methods/properties in your LotusScript agent, telling you how often each one was executed and how long they took to execute. In Notes/Domino 7, the second (security) tab of Agent properties now includes a checkbox labeled Profile this agent. You can select this option if you want an agent to be profiled. The next time the agent runs, a profile document in the database is created and filled with the information from that execution. This document is then updated every time the agent runs. You can view these results from the Agent View by highlighting your agent and selecting Agent | View Profile Results. The following is a profile for an agent that performed slow mail searches: Although this doesn't completely measure (and certainly does not completely troubleshoot) your agents, it is an important step forward in troubleshooting code. Imagine the alternative: dozens of print statements, and then hours of collating results! Summary In closing, we hope that this article has opened your eyes to new possibilities in troubleshooting, both in terms of techniques and new Notes/Domino 7 features. Every environment has applications that users wish ran faster, but with a bit of care, you can troubleshoot your performance problems and find resolutions. After you have your servers running Notes/Domino 7, you can use DDM and Agent Profiler (both exceptionally easy to use) to help nail down poorly performing code in your applications. These tools really open a window on what had previously been a room full of mysterious behavior. Full-text indexing on the fly, code that uses too much memory, and long running agents are all quickly identified by Domino Domain Monitoring (DDM). Try it!
Read more
  • 0
  • 0
  • 3072
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-layouts-ext-js
Packt
23 Oct 2009
9 min read
Save for later

Layouts in Ext JS

Packt
23 Oct 2009
9 min read
What are layouts, regions, and viewports? Ext uses Panels, which are the basis of most layouts. We have used some of these, such as FormPanel and GridPanel, already. A viewport is a special panel-like component that encloses the entire layout, fitting it into the whole visible area of our browser. For our first example, we are going to use a viewport with a border layout that will encapsulate many panels. A viewport has regions that are laid out in the same way as a compass, with North,South, East and West regions—the Center region represents what's left over in the middle. These directions tell the panels where to align themselves within the viewport and, if you use them, where the resizable borders are to be placed: The example we're creating will look like the following image, and combines many of the previous examples we have created: This layout is what's called a 'border' layout, which means that each region is separated by a somewhat three dimensional border bar that can be dragged to resize the regions. This example contains four panel regions: North: The toolbar West: A form Center: Grid in a tab panel East: A plain panel containing text Note that there is no 'South' panel in this example—not every region needs to be used in every layout. Our first layout Before we create our layout that uses only four regions let's go ahead and create a layout that utilizes all the regions, and then remove the South panel. We are going to create all of the regions as 'panels', which can be thought of as blank canvases to which we will add text, HTML, images, or even Ext JS widgets. var viewport = new Ext.Viewport({ layout: 'border', renderTo: Ext.getBody(), items: [{ region: 'north', xtype: 'panel', html: 'North' },{ region: 'west', xtype: 'panel', split: true, width: 200, html: 'West' },{ region: 'center', xtype: 'panel', html: 'Center' },{ region: 'east', xtype: 'panel', split: true, width: 200, html: 'East' },{ region: 'south', xtype: 'panel', html: 'South' }]}); Each region is defined as one of the four compass directions—East, West, North, and South. The remainder in the middle is called the center region, which will expand to fill all of the remaining space. Just to take up some blank space in each region and to give a visual indicator as to where the panels are, we defined an 'HTML' config that has just text. (This could also contain complex HTML if needed, but there are better ways to set the contents of panels which we will learn about soon). Ext JS provides an easy, cross-browser compatible, speedy way to get a reference to the body element, by using Ext.getBody(). If everything works out ok, you should see a browser that looks like this: Now we have a layout with all five regions defined. These regions can have other text widgets added into them, seamlessly, by using the xtype config. Alternatively they can be divided up separately into more nested regions—for instance, the center could be split horizontally to have its own South section. A 'Center' region must always be defined. If one is not defined, the layout will produce errors and appear as a jumbled set of boxes in the browser. Splitting the regions The dividers are set up for each panel by setting the split flag—the positioning of the dividers is determined automatically based on the region the panel is in. split: true For this page, we have set the West and East regions as 'split' regions. This, by default, makes the border into a resizing element for the user to change the size of that panel. I want options Typically, when a split is used, it's combined with a few other options that make the section more useful, such as width, minSize, and collapseMode. Here are some of the more commonly-used options: Option Value Description split true/false Boolean value that places a resizable bar between the sections collapsible true/false Boolean value that adds a button to the title bar which lets the user collapse the region with a single click collapseMode Only option is mini mode, or undefined for normal mode When set to 'mini', this adds a smaller collapse button that's located on the divider bar, in addition to the larger collapse button on title bar; the panel also collapses into a smaller space title String Title string placed in the title bar bodyStyle CSS CSS styles applied to the body element of the panel. minSize Pixels, ie: 200 The smallest size that the user can drag this panel to maxSize Pixels, ie: 250 The largest size that the user can drag this panel to margins In pixels: top, right, bottom, left, i.e.,: 3 0 3 3 Can be used to space the panel away from the edges or away from other panels; spacing is applied outside of the body of the panel cmargins In pixels: top, right, bottom, left, i.e.,: 3 0 3 3 Same idea as margins, but applies only when the panel is collapsed   Let's add a couple of these options to our west panel: { region: 'west', xtype: 'panel', split: true, collapsible: true, collapseMode: 'mini', title: 'Some Info', bodyStyle:'padding:5px;', width: 200, minSize: 200, html: 'West'} Adding these config options to our west panel would give us the following look: Expanding and collapsing a panel that does not have a width specified can produce rendering problems. Therefore, it's best to specify a width for panels—of course this is not needed for the center, as this panel automatically fills the remaining space. Tab panels With Ext JS, tab panels are also referred to as a "card" layout because they work much like a deck of cards where each card is layered directly above or below the others and can be moved to the top of the deck, to be visible. We also get pretty much the same functionality in our tab panel as a regular panel, including a title, toolbars, and all the other usual suspects (excluding tools). Adding a tab panel If the Ext JS component is a panel type component, for instance GridPanel andFormPanel, then we can add it directly to the layout using its xtype. Let's start by creating a tabPanel: { region: 'center', xtype: 'tabpanel', items: [{ title: 'Movie Grid', html: 'Center' }]} The items config is an array of objects that defines each of the tabs contained in this tabpanel. The title is the only option that's actually needed to give us a tab, and right now html is just being used as a placeholder, to give our empty tab some content. We will also need to add an activeTab config that is set to zero to our tab panel. This is the index of the tabs in the panel left to right starting with zero and counting up for each tab. This tells the tab panel at position zero to make itself active by default, otherwise, we would have no tabs displayed, resulting in a blank section until the user clicked a tab. { region: 'center', xtype: 'tabpanel', activeTab: 0, items: [{ title: 'Movie Grid', html: 'Center' }]} If we take a look at this in a browser, we should see a tab panel in the center section of our layout. Adding more tabs is as easy as adding more items into the items array. Each tab item is basically its own panel, which is shown or hidden, based on the tab title that has been clicked on the tab panel. { region: 'center', xtype: 'tabpanel', activeTab: 0, items: [{ title: 'Movie Grid', html: 'Center' },{ title: 'Movie Descriptions', html: 'Movie Info' }]} Both the Movie Grid and Movie Descriptions tabs are just plain panels right now. So let's add some more configuration options and widgets to them. Widgets everywhere Earlier, I mentioned that any type of panel widget could be added directly to a layout, just as we had done with the tabs. Let's explore this by adding another widget to our layout—the grid. Adding a grid into the tabpanel As we now have these tabs as part of our layout, let's start by adding a grid panel to one of the tabs. Adding the xtype config option to the grid config code will produce a grid that fills one entire tab: { region: 'center', xtype: 'tabpanel', activeTab: 0, items: [{ title: 'Movie Grid', xtype: 'gridpanel', store: store, autoExpandColumn: 'title', columns: // add column model //, view: // add grid view spec // },{ title: 'Movie Descriptions', html: 'Movie Info' }]} xtypes offer a quick way to instantiate a new component with minimal typing. This is sometimes referred to as 'lazy rendering' because the components sit around waiting to be displayed before they actually execute any code. This method can help conserve memory in your web application. As we are adding this grid to a tab—which is essentially just a panel—there are some things that we no longer need (like the renderTo option, width, height, and a frame).The size, title, and border for the grid are now handled by our tab panel. Now we should have a layout that looks like this: Accordions The accordion is a very useful layout that works somewhat like a tab panel, where we have multiple sections occupying the same space, with only one showing at a time. This type of layout is commonly used when we're lacking the horizontal space needed for a tab panel, but instead have more vertical space available. When one of the accordion panels is expanded, the others will collapse. Expanding and collapsing the panels can be done either by clicking the panel's title bar or by clicking the plus/minus icons along the rightmost side of the panel.    
Read more
  • 0
  • 0
  • 4840

article-image-simple-pocket-pc-application-using-visual-studio-2005
Packt
23 Oct 2009
5 min read
Save for later

A Simple Pocket PC Application using Visual Studio 2005

Packt
23 Oct 2009
5 min read
Creating a Device Application File | New | Project will open the New Project window as shown. Expand the Visual Basic node and follow it up by expanding the Smart Device node as shown. There are three kinds of Smart Devices listed; Pocket PC 2003, Smartphone 2003 and Windows CE 5.0. For this article the Pocket PC 2003 is chosen. When you select Pocket PC 2003 in the left pane, the right hand pane shows many templates available for Pocket PC 2003. You will be able to create the application for CF 1.0 as well as CF 2.0. In this interface you may choose to create the following types of applications: Device Application: CF2.0 Forms APP for Pocket PC 2003 or later Device Application(1.0: CF1.0 Forms APP for Pocket PC 2003 or later Console Application: CF 2.0 non-graphic application Console Application(1.0: CF 1.0 non-graphic application Control Library : CF 2.0 controls for Pocket PC Class library can be used for creating dll's. Change the name of the default project name to something different. Here it is changed to Pocket2. When you click OK after changing the name of the project, the program creates a MyProject folder and a Form1.vb file which you see under Solution Explorer. You may rename the file. The interface functions very much like, as if you are creating a Windows Application. The difference is you will be displaying a small foot print device as shown in the next figure. Form1 is displayed in the design mode and a mainMenu1 item is added to the Control Tray. When you click on the mainMenu1 in the tray you get a visible cue as to what you should do next as shown. The mainMenu1 shows up with Smart Tasks as shown. Now click on the Edit Menu and this opens up the Type Here area where you can enter some text. Here "Test" has been entered. This will create a single menu item "Test". This is a nice interface where you can build up menu items very easily as shown in the next figure. All you need to do is just type in the area indicated by "Type Here". In addition to this you may also use other common controls from the toolbox. Placing Other Controls on the Form Because of the compact nature of the device with a reduced foot print, the controls available are a subset of the controls that you find normally in a desktop application. Where as controls in desktop can take a variety of arguments, the compact controls work with limited set of arguments. The next figure shows the device related controls that are available. Let us go ahead and drag and drop (or double click in the Toolbox), a DateTime Picker control and a textbox as shown in the next figure. Rearranging objects is a snap because Visual Studio 2005 has an excellent support for sizing and aligning objects. The grid lines automatically snap in place (notice the thin blue line tying the alignment of Textbox1 with the DataTimePicker control. The Form1 text was changed using the Form's property window to read "Testing a simple device". Attaching an Event to Test the Controls Let us make use of the click event of the TestTime sub menu item to read from the DataTimePicker control and display it in the Textbox. To begin with, let us make the Textbox's text to be empty. Using the code shown the next paragraph we can show the date we pick from the DataTimePicker to display in the textbox. You can get to the code page by clicking on the TestTime sub menu [MenuItem3] item in the design window. Note Form1.vb is renamed as MyFirstMobile.vb Books from Packt Software Testing with Visual Studio Team System 2008 Entity Framework Tutorial Microsoft AJAX Library Essentials: Client-side ASP.NET AJAX 1.0 Explained ASP.NET Data Presentation Controls Essentials Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C# Visual SourceSafe 2005 Software Configuration Management in Practice LINQ Quickly BlackBerry Enterprise Server for Microsoft® Exchange   Testing the Device Click on the Build menu item to display the drop-down menu and choose to build the project. After the Build succeeds (you should see a build succeeded message at the bottom of the screen) click on Start Debugging (green arrow) by the side of the Debug menu item. This displays the Deploy Pocket2 window as shown. There are a number of Pocket PC devices shown with the highlighted as the default. Accept the default emulator and click on the Deploy button. When the deployment succeeds you should see a message to that effect in the Output window (you may access this from the View menu item). You will also see the emulator skin as shown in the next figure. Which changes into the following when the program gets loaded. Now click on the DateTimePicker control, pick a date as shown in the next figure. After picking the date click on the sub menu item of Test which is TestTime. This transfers the date information from the DateTimePicker and places it in the textbox after adding some text as shown. You may pick another date and test it again. When you try to close the device by hitting the close button at the top of the window the following window gets displayed. If you choose Yes, the device state gets saved and the next message gets displayed. Although a Pocket PC emulator was chosen you could get all the accessible devices using the Device Emulator sub menu item from the Tools menu as shown. When you click on the Device Emulation Manager... you will see all the available devices as shown. Get acquainted with the Object Browser The Object Browser is one place where you may find clues as to what is happening in your program, whether you are using the correct syntax, etc. Refer to this important resource as you develop your programs. Summary This article described a simple introductory application for mobile devices. The application deployment to a Pocket PC emulator was also described.
Read more
  • 0
  • 0
  • 4050

article-image-windows-presentation-foundation-project-basics-working
Packt
23 Oct 2009
7 min read
Save for later

Windows Presentation Foundation Project - Basics of Working

Packt
23 Oct 2009
7 min read
Introduction WPF, an acronym for Windows Presentation Foundation is a subsystem of class libraries for WinFX and it enables the user to get a richer experience bringing together UI, Documents, media etc. A XAML (Extensible Application Markup Language) file which is at the heart of a WPF project can be created in several ways that includes the Notepad text editor, the Expression Blend which requires another download from Microsoft, but may not provide a easy to use XAML file to use in VS, and the Visual Studio editions except the express edition. XAML is presently specific to windows platform and is a XML formatting language and not an application programming interface. I will be mostly showing how to get some hands-on experience with a WPF project using the Visual Studio 2005 interface and the template files that you may access with the Windows SDK installed. Creating a WPF Project From File | New | Project click open the New Project window as shown in the next figure. Click on Visual Basic and expand its contents. Under .NET 3.0 FrameWork (It is assumed that you have installed NET 3.0 Framework) choose the Windows Application (WPF). Now highlight the Windows Application (WPF) and change the name of the application to some name of your choice. For this article it is changed to AppWPF. Click on the OK button after typing a name of your choice. This creates the necessary file/folders for the application as shown in the next figure. There are two XAML files created in the project. The App.xaml and the Windows1.xaml file. Delete the Windows1.xaml and add a new item as shown with the name BasicControls.xaml. With this new item added you may need to change the App.xaml file as shown below. <Application x_Class="App" StartupUri="BasicControls.xaml"> <Application.Resources> </Application.Resources> </Application> The StartupUri has been changed from the original Windows1.xaml to BasicControls.xaml. With this change made you can now display the BasicControls.xaml file together with its design as shown in the next figure. This represents a 300 X 300 window which can be used as a container for other controls. You also notice the reference to the namespaces that are required and the XML syntax with the attribute of the project for the window. Placing Controls on the Window Placing Controls automatically creates XAML code. Placing controls on this window is as easy as dragging from the Tools and dropping on to this window. The next picture shows a button and a textbox dragged and dropped onto this window. The necessary code for these controls gets automatically added as the controls are placed. After the two controls are added, the xaml file gets changed as shown. The Button and Textbox properties are the defaults which may be modified as will be seen later in the article. <Window x_Class="BasicControls" Title="AppWPF" Height="300" Width="300" > <Grid> <Button Height="23" Margin="94,0,123,39" Name="Button1" VerticalAlignment="Bottom">Button</Button> <TextBox HorizontalAlignment="Left" Margin="43, 126, 0,115" Name="TextBox1" Width="100"></TextBox> </Grid> </Window> Adding code automatically updates the window design. Inserting a declarative code into the BasicControls.xaml file will automatically add the control defined by that code to the design window. Add this code to the xaml file after as shown in the next paragraph. As soon as you type "<", the intellisense gets fired up and you will see a drop-down list of items that you can insert as shown in the next figure. Now you click on the Textbox (or whatever else you wish to place). This adds to the xaml file. Now to the opening tag of the textbox, you add a name attribute and call it TextBox2. Intellisense is also used in adding attributes as you will get a context sensitive listing of attributes for the chosen control. Also add other attributes such as width, height, alignment etc. With the code added as shown in the next paragraph you will see that the design pane has a new textbox as shown in the next figure.   <Textbox Name="TextBox2" Height="20" Margin="89.5,96.5,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="50"></TextBox*gt; The property window for the TextBox2 shown can also be used to make changes. You can also move, or adjust the dimensions of the controls using the mouse. The various controls provide a very rich interface for the designer in manipulating the controls. Event Handling All 'Hello World' programs used a button click to demonstrate the workings of the code or how the events were handled. In this tutorial also you will demonstrate the click event along the same lines. In the Solution Explorer only a few items are seen but there are lot more files in the project. Click on the middle toolbar just above the project as shown in the next figure. This will allow you to see all the files / folders in the project displayed (every folder expanded out) as shown. This is vastly different from a legacy windows project. The references to the Presentation Foundation are all in the three references, PresentationCore, PresentationDesignDeveloper and PresentationDesignFramework. In order to appreciate the rich designer support you have to go to the ,Object Browser and look at the references. For example just the PresentationCore has the following namespaces shown in the next figure. The BasicControls.xaml file also has the code behind file, BasicControls.xaml.vb, as shown in the next figure. In the code page, the drop-down control displaying BasicControls presently has all the objects on this window listed in its menu. You can find the Button as well. With the button chosen you can use the second drop-down to access all the events of the Button in the second drop-down (presently showing Declarations). In this manner the button click event was chosen from the second drop-down. Here the Button1_Click has been set to display "Click is registered" in Textbox1 when the button is clicked. You can find the reference to this in the Object Browser as shown in the next figure. Object Browser is an extremely valuable resource that you should seek out to understand the underlying logic, the arguments of a function call, etc. When you build and execute the program and click on the button this is what you will see displayed. The top part is the design window and the bottom is the window when clicked. At this point you might be wondering how to improve the look and feel. Indeed the form looks drab since none of the properties have been used except for the most basic. The next figure shows how you may change the appearance by inserting the property attributes directly into the XMAL file. You will be better off using the intellisense rather than trying to guess the property based on your previous 'Windows' experience as shown in the next figure. You may also add attributes from the property window of the object which you can view when the object is highlighted (or clicked) in the design pane. The variety of attributes is just too many and when in doubt you will be able to drill down to the one you want to use in the Object Browser. The next code listing shows a few more attributes added to the Textbox1. As you might have seen in the intellisense pop-up windows, there is a large number of properties that you can tweak and events that you can trigger. Notice the [.] notation for the TextElement in the code listing, FontFamily being the child of the parent TextElement. Listing 1 <TextBox HorizontalAlignment="Left" Margin="43,126,0,115" Name="TextBox1" Width="150" TextElement.FontFamily="Times Roman" ToolTip="Xaml TextBox" FontWeight="Bold" AutoWordSelection="True" Foreground="BlueViolet" Background="Aquamarine" TextDecorations="Underline" > </TextBox> When the program is executed you will see the following displayed. Summary The article describes the steps to create a WPF project. The Design <-->Declarative Code interactivity is also described. The placing of controls and adding event handling code to the code behind page is explained with an example. While testing the "AutoWordSelection" did not function as it should by its definition. You may look up this in the 'Help'.
Read more
  • 0
  • 0
  • 2117

article-image-prototyping-javascript
Packt
23 Oct 2009
7 min read
Save for later

Prototyping JavaScript

Packt
23 Oct 2009
7 min read
In this article by Stoyan Stefanov, you'll learn about the prototype property of the function objects. Understanding how the prototype works is an important part of learning the JavaScript language. After all, JavaScript is classified as having a prototype-based object model. There's nothing particularly difficult about the prototype, but it is a new concept and as such may sometimes take some time to sink in. It's one of these things in JavaScript (closures are another) which, once you "get" them, they seem so obvious and make perfect sense. As with the rest of the article, you're strongly encouraged to type in and play around with the examples; this makes it much easier to learn and remember the concepts. The following topics are discussed in this article: Every function has a prototype property and it contains an object Adding properties to the prototype object Using the properties added to the prototype The difference between own properties and properties of the prototype __proto__, the secret link every object keeps to its prototype Methods such as isPrototypeOf(), hasOwnProperty(), and propertyIsEnumerable() The prototype Property The functions in JavaScript are objects and they contain methods and properties. Some of the common methods are apply() and call() and some of the common properties are length and constructor. Another property of the function objects is prototype. If you define a simple function foo() you can access its properties as you would do with any other object: >>>function foo(a, b){return a * b;}>>>foo.length 2 >>>foo.constructor Function() prototype is a property that gets created as soon as you define the function. Its initial value is an empty object. >>>typeof foo.prototype "object" It's as if you added this property yourself like this: >>>foo.prototype = {} You can augment this empty object with properties and methods. They won't have any effect of the foo() function itself; they'll only be used when you use foo()as a constructor. Adding Methods and Properties Using the Prototype Constructor functions can be used to create (construct) new objects. The main idea is that inside a function invoked with new you have access to the value this, which contains the object to be returned by the constructor. Augmenting (adding methods and properties to) this object is the way to add functionality to the object being created. Let's take a look at the constructor function Gadget() which uses this to add two properties and one method to the objects it creates. function Gadget(name, color) {   this.name = name;   this.color = color;   this.whatAreYou = function(){    return 'I am a ' + this.color + ' ' + this.name;   }} Adding methods and properties to the prototype property of the constructor function is another way to add functionality to the objects this constructor produces. Let's add two more properties, price and rating, and a getInfo() method. Since prototype contains an object, you can just keep adding to it like this: Gadget.prototype.price = 100;Gadget.prototype.rating = 3;Gadget.prototype.getInfo = function() {   return 'Rating: ' + this.rating + ', price: ' + this.price;}; Instead of adding to the prototype object, another way to achieve the above result is to overwrite the prototype completely, replacing it with an object of your choice: Gadget.prototype = {   price: 100,   rating: 3,   getInfo: function() {    return 'Rating: ' + this.rating + ', price: ' + this.price;   }}; Using the Prototype's Methods and Properties All the methods and properties you have added to the prototype are directly available as soon as you create a new object using the constructor. If you create a newtoy object using the Gadget() constructor, you can access all the methods and properties already defined. >>> var newtoy = new Gadget('webcam', 'black');>>> newtoy.name; "webcam" >>> newtoy.color; "black" >>> newtoy.whatAreYou(); "I am a black webcam" >>> newtoy.price; 100 >>> newtoy.rating; 3 >>> newtoy.getInfo(); "Rating: 3, price: 100" It's important to note that the prototype is "live". Objects are passed by reference in JavaScript, and therefore the prototype is not copied with every new object instance. What does this mean in practice? It means that you can modify the prototype at any time and all objects (even those created before the modification) will inherit the changes. Let's continue the example, adding a new method to the prototype: Gadget.prototype.get = function(what) {   return this[what];}; Even though newtoy was created before the get() method was defined, newtoy will still have access to the new method: >>> newtoy.get('price'); 100 >>> newtoy.get('color'); "black" Own Properties versus prototype Properties In the example above getInfo() used this internally to address the object. It could've also used Gadget.prototype to achieve the same result: Gadget.prototype.getInfo = function() {   return 'Rating: ' + Gadget.prototype.rating + ', price: ' + Gadget.prototype.price;}; What's is the difference? To answer this question, let's examine how the prototype works in more detail. Let's again take our newtoy object: >>> var newtoy = new Gadget('webcam', 'black'); When you try to access a property of newtoy, say newtoy.name the JavaScript engine will look through all of the properties of the object searching for one called name and, if it finds it, will return its value. >>> newtoy.name "webcam" What if you try to access the rating property? The JavaScript engine will examine all of the properties of newtoy and will not find the one called rating. Then the script engine will identify the prototype of the constructor function used to create this object (same as if you do newtoy.constructor.prototype). If the property is found in the prototype, this property is used. >>> newtoy.rating 3 This would be the same as if you accessed the prototype directly. Every object has a constructor property, which is a reference to the function that created the object, so in our case: >>> newtoy.constructor Gadget(name, color) >>> newtoy.constructor.prototype.rating 3 Now let's take this lookup one step further. Every object has a constructor. The prototype is an object, so it must have a constructor too. Which in turn has a prototype. In other words you can do: >>> newtoy.constructor.prototype.constructor Gadget(name, color) >>> newtoy.constructor.prototype.constructor.prototype Object price=100 rating=3 This might go on for a while, depending on how long the prototype chain is, but you eventually end up with the built-in Object() object, which is the highest-level parent. In practice, this means that if you try newtoy.toString() and newtoy doesn't have an own toString() method and its prototype doesn't either, in the end you'll get the Object's toString() >>> newtoy.toString() "[object Object]" Overwriting Prototype's Property withOwn Property As the above discussion demonstrates, if one of your objects doesn't have a certain property of its own, it can use one (if exists) somewhere up the prototype chain. What if the object does have its own property and the prototype also has one with the same name? The own property takes precedence over the prototype's. Let's have a scenario where a property name exists both as an own property and as a property of the prototype object: function Gadget(name) {   this.name = name;}Gadget.prototype.name = 'foo'; "foo" Creating a new object and accessing its name property gives you the object's ownname property. >>> var toy = new Gadget('camera');>>> toy.name; "camera" If you delete this property, the prototype's property with the same name"shines through": >>> delete toy.name; true >>> toy.name; "foo" Of course, you can always re-create the object's own property: >>> toy.name = 'camera';>>> toy.name; "camera"  
Read more
  • 0
  • 0
  • 6696
article-image-openid-ultimate-sign
Packt
23 Oct 2009
13 min read
Save for later

OpenID: The Ultimate Sign On

Packt
23 Oct 2009
13 min read
Introduction How many times have you walked away from some Internet forum because you could not remember your login ID or password, and just did not want to go through the tedium of registering again? Or gone back to re-register yourself only to forget you password the next day? Remembering all those login IDs and passwords is indeed an onerous task and one more registration for a new site seems like one too many. We have all tried to get around these problems by jotting down passwords on pieces of paper or sticking notes to our terminal – all potentially dangerous practices that defeat the very purpose of keeping a digital identity secure. If you had the choice of a single user ID and password combination – essentially a single digital identity – imagine how easy it might become to sign up or sign in to new sites. Suppose you could also host your own digital identity or get it hosted by third party providers who you could change at will, or create different identity profiles for different classes of sites, or choose when your User ID with a particular site should expire; suppose you could do all this and more in a free, non-proprietary, open standards based, extensible, community-driven framework (whew!) with Open Source libraries and helpful tutorials to get you on board, you would say: “OpenID”. To borrow a quote from the OpenID website openid.net: “OpenID is an open, decentralized, free framework for user-centric digital identity.” The Concept The concept itself is not new (and there are proprietary authentication frameworks already in existence). We are all aware of reference checks or identity documents where a reliable agency is asked to vouch for your credentials. A Passport or a Driver's License is a familiar example. Web sites, especially those that transact business, have digital certificates provided by a reliable Certification Authority so that they can prove to you, the site visitor, they are indeed who they claim to be. From here, it does not require a great stretch of imagination to appreciate that an individual netizen can have his or her own digital identity based on similar principles. This is how you get the show on the road. First, you need to get yourself a personal identity based on OpenID from one of the numerous OpenID providers[1] or some sites that provide an OpenID with membership. This personal identity comes in the form a URL or URI (essentially a web address that starts with http:// or https://) that is unique to you. When you need to sign up or sign in to a web site that accepts OpenID logins (look for the words 'OpenID' or the OpenID logo), you submit your OpenID URL. The web site then redirects you to the site of your ID provider where you authenticate yourself with your password and optionally choose the details – such as full name, e-mail ID, or nickname, or when your login ID should expire for a particular site – that you want to share with the requesting site and allow the authentication request to go through. You are then returned to the requesting site. That is all there is to it. You are authenticated! The requesting site will usually ask you to associate a nickname with your OpenID. It should be possible to register with and sign in to different sites using different nicknames – one for each site – but the same OpenID. But you may not want to overdo this lest you get into trouble trying to recall the right nickname for a particular site. Just Enough Detail This is not a technical how-to. For serious technical details, you can follow the excellent links in the References section. This is a basic guide to get you started with OpenID, to show you how flexible it is, and to give pointers to its technical intricacies. By the end of this article you should be able to create your own personal digital identities based on OpenID (or discover if you already have one – you just might!), and be able to use them effectively. In the following sections, I have used some real web sites as examples. These are only for the purpose of illustration and in no way shows any preference or endorsement. Getting Your OpenID The simplest and most direct way to get your personal OpenID is to go to a third party provider. But before that, the smart thing to do would be find out if you already have one. For instance, if you blog at wordpress.com, then http://yourblogname.wordpress.com is an OpenID already available to you. There are other sites[1], too, that automatically provide you an OpenID with membership. Yahoo! gives you an OpenID if you have an account with them; but it is not automatic and you need to sign up for it at http://openid.yahoo.com. Your OpenID at Yahoo! will be of the form https://me.yahoo.com/your-nickname. To get your third party hosted OpenID we will choose Verisignlab's Personal Identity Provider (PIP) site -- http://pip.verisignlabs.com/ as an example. You are of course free to decide and choose your own provider(s). The sign up form is a simple no-fuss affair with the minimum number of fields. (If you are tired of hearing 'third party', the reason for using the term will get clearer further on. For the purpose of this article, you, the owner of the OpenID are the first party, the web site that wants you authenticated is the second party, the OpenID provider being the third.) After replying to the confirmation e-mail you are ready to take on the wide world with your OpenID. If you gave your ID as 'johndoe' then you will get an OpenID like: http://johndoe.pip.verisignlabs.com. You can come back to the PIP site and update your profile; some sites request information such as full name or e-mail ID but you are always in control whether you want to pass on this information back to them. If you choose to have just one OpenID, then this is about as much as you would ever do to sign on to any OpenID enabled site. You can also create multiple OpenID's for yourself – remember what we said earlier about having multiple ID's to suite different classes of sites. Testing Your OpenID Now that we have our OpenID we will test it and in the process also see how a typical OpenID-based authentication works in practice. Use the testing form[7] in the References section and enter your OpenID URL that you want tested. When you are redirected to your PIP's site (we are sticking to our Verisign example), enter your password and also choose what information you want passed back to the requesting site before clicking “Allow” to let the authentication go through. Important tip: Enter your password only on the PIP's site and nowhere else! Be aware that this particular testing page may not work with all OpenIDs; that may not necessarily mean that the OpenID itself has a problem. Step-by-Step: Use your WordPress or Verisign OpenID For this tutorial part, we will take the example of http://www.propeller.com (a voting site among other things) that accepts OpenID sign ups and sign ins. For an OpenID we will use the URL of your WordPress blog – http://yourblogname.wordpress.com. You could also use your OpenID URL (the one you got from the Verisign example) and follow through. On the Propeller site, go to the sign up page. Look for the prominent OpenID logo. Type in your OpenID URL and click on the 'Verify ...' button. You are taken to the site of your PIP where you need to authenticate yourself.   If you used your Verisign OpenID, enter your password, complete the details you want to pass back to the requesting site (remember, we are trying to sign up with Propeller) and allow the authentication to go through. You are now back with the Propeller site. Just hang in there a moment as we check the flow for a Wordpress OpenID.   For a WordPress OpenID, you will get a screen instead that asks you to deliberately sign in to your WordPress account. Once you are signed in, you will see a hyperlink that prompts you to continue with the authentication request from Propeller.     Follow this link to a form that asks your permission to pass back information to Propeller such your nickname and e-mail ID. You can change both these fields if you wish and allow the authentication to go through.   Now you should be back at the Propeller site with a successful OpenID verification. The site will ask you to associate a nickname with your OpenID and a working e-mail to complete your registration process. This step is no different from a normal sign up process. Check your e-mail, click on the link provided therein, get back to the Propeller site, and click another link to complete the registration process. You are automatically signed in to Propeller. Sign out for the moment so that we can see how an OpenID sign in works. Go to the sign in page at Propeller. You will see a normal sign in and an OpenID sign in. We will use the OpenID one (of course!). Type in your OpenID URL and click on the “Sign in...” button. Complete the formalities on your PIP site (for Verisign you will get a sign in page; for Wordpress you will need to sign in first unless you are already signed in) and let the authentication go through. This time you are back on the Propeller site all signed in and ready to go. Note that your nickname appears correctly because your OpenID is associated with it. That is all there is to it. Easier done than said. Try this a couple of times and I bet it will feel easier than the remote control of your home entertainment system! Your Custom OpenID URL If you want a personalized OpenID URL and do not like the one provided by your PIP you can always use delegation to get what you want. To make your blog or personal home page as your OpenID URL, insert the following in the head portion (the part that falls between <head> and </head> on an HTML page) of your blog or any page that you own. This will only work with pages that you completely own and have control over their source. There is a Wordpress plug-in that gives delegating capability to your Wordpress.com blog but we will not go into that here. The first URL is your OpenID server. The second URL is your OpenID URL – either the one you host yourself or the one provided by a third party. The requesting site discovers your OpenID and correctly authenticates you. With this approach you can switch providers transparently. At the risk of repeating: test your new personalized URL before you start using it. Note that the 'openid.server' URL may vary depending on the PIP. To get the name of your PIP's OpenID server, use the testing service[7] which reports the correct URL for your PIP to use with the “openid.server” part your delegation mark up. <link rel="openid.server" href="http://pip.verisignlabs.com/server" /><link rel="openid.delegate" href="http://johndoe.pip.verisignlabs.com/" /> Rolling Your Own If you are paranoid about entrusting the management of your digital identity to another web site and also have the technical smarts to match, there are ways you can become your own PIP[5][6]. If you are tech-savvy then you cannot fail to appreciate the elegance of the OpenID architecture and the way it lets control stay where it should – with you. Account Management – Lite? OpenID makes life easier for site visitors. But what about the site and the domain administrators? If administrators decide to go the OpenID way[3], it lightens their load by taking away a major part of the chore of membership administration and authentication. As a bonus, it also potentially opens up a site to the entire community of net users that have OpenID's or are getting one. Security and Reliability As the wisecrack goes – if you want complete security, you should unplug from the Internet. On a serious note, there are some precautions you have to take while using OpenID and they are no different from the precautions you would take for any item associated with your identity, say your Passport or your credit card. Remember to enter your password only on the Identity Provider's site and nowhere else. Be alert to phishing. This explains why WordPress asks you to log in explicitly rather than take you directly to their authentication page. Never use your e-mail ID handle as your OpenID name but use a different one. Using OpenID has its flip side, too. Getting your OpenID from a provider potentially lays open your browsing habits to tracking. You can get around this by being your own PIP, delegating from your own domain, or creating a PIP profile under an alias. There is the possibility that your OpenID provider goes out of service or worse, out of business. It is thus important to choose a reliable identity provider. There are sites that allow you to associate multiple OpenIDs with your account and perhaps this can be a way forward to popularize OpenID and to allay any fears of getting locked in with a single vendor and getting locked out of your identity in the process. Your Call There are many sites today that are not OpenID-ready. There are some sites that allow only OpenID sign ons. However, if you see the elegance of the OpenID mechanism and the convenience it provides both site administrators and members, you might agree that its time has come. Get an OpenID if you do not have one. Convince your friends to get theirs. And if you run an online community or are a member of one, throw your weight around to ensure that your site also provides an OpenID sign on. References http://wiki.openid.net/OpenIDServers is a list of ID providers. http://blogs.zdnet.com/digitalID/?p=78 makes a strong case for OpenID. Read it to get a good perspective on the subject. http://www.plaxo.com/api/openid_recipe is a soup-to-nuts tutorial on how to enable your site for OpenID authentication or migrate to OpenID from your current site-specific authentication scheme. Check out http://www.openidenabled.com/php-openid/ if you are looking for software libraries to OpenID-enable your site. http://www.intertwingly.net/blog/2007/01/03/OpenID-for-non-SuperUsers is a crisp if intermediate-level how-to that lets you try out new things in the OpenID space. http://siege.org/projects/phpMyID/ shows you how you can run your own (yes, your own) PIP server. http://www.openidenabled.com/resources/openid-test/checkup is a link that helps you test your OpenID. Once you get your OpenID, you can submit it to the form on this URL and get yourself authenticated to see if everything works fine. Does not seem to work with Wordpress and Yahoo! OpenIDs as of this writing. http://www.openid.net is the OpenID site.   Read another article by Gurudutt Talgery Podcasting with Linux Command Line Tools and Audacity  
Read more
  • 0
  • 0
  • 5681

article-image-jboss-perspective
Packt
23 Oct 2009
4 min read
Save for later

JBoss AS Perspective

Packt
23 Oct 2009
4 min read
As you know, Eclipse offers an ingenious system of perspectives that helps us to switch between different technologies and to keep the main-screen as clean as possible. Every perspective is made of a set of components that can be added/removed by the user. These components are known as views. The JBoss AS Perspective has a set of specific views as follows: JBoss Server View Project Archives View Console View Properties View For launching the JBoss AS Perspective (or any other perspective), follow these two simple steps: From the Window menu, select Open Perspective | Other article. In the Open Perspective window, select the JBoss AS option and click on OK button (as shown in the following screenshot). If everything works fine, you should see the JBoss AS perspective as shown in the following screenshot: If any of these views is not available by default in your JBoss AS perspective, then you can add it manually by selecting from the Window menu the Show View | Other option. In the Show View window (shown in the following screenshot), you just select the desired view and click on the OK button. JBoss Server View This view contains a simple toolbar known as JBoss Server View Toolbar and two panels that separate the list of servers (top part) from the list of additional information about the selected server (bottom part). Note that the quantity of additional information is directly related to the server type. Top part of JBoss Server View In the top part of the JBoss Server View, we can see a list of our servers, their states, and if they are running or if they have stopped. Starting the JBoss AS The simplest ways to start our JBoss AS server are: Select the JBoss 4.2 Server from the server list and click the Start the server button from the JBoss Server View Toolbar (as shown in the following screenshot). Select the JBoss 4.2 Server from the server list and right-click on it. From the context menu, select the Start option (as shown in the following screenshot). In both cases, a detailed evolution of the startup process will be displayed in the Console View, as you can see in the following screenshot. Stopping the JBoss AS The simplest ways to stop JBoss AS server are: Select the JBoss 4.2 Server from the server list and click the Stop the server button from the JBoss Server View Toolbar. Select the JBoss 4.2 Server from the server list and right-click on it. From the context menu, select the Stop option. In both cases, a detailed evolution of the stopping process will be displayed in the Console View, as you can see in the following screenshot. Additional operations on JBoss AS Beside Start and Stop operations, JBoss Server View allows us to: Add a new server (the New Server option from the contextual menu) Remove an existing server (the Delete option from the contextual menu) Start the server in debug mode (first button on the JBoss Server View Toolbar) Start the server in profiling mode (third button on the JBoss Server View Toolbar) Publish to the server or synching the publish information between the server and the workspace (the Publish option from the contextual menu or the last button on the JBoss Server View Toolbar) Discard all publish state and republish from scratch (the Clean option from the contextual menu) Twiddle server (the Twiddle Server option from the contextual menu) Edit launch configuration (the Edit Launch Configuration option from the contextual menu as shown in the following screenshot). Add/remove projects (the Add and Remove Projects option from the contextual menu) Double-click the server name and modify parts of that server in the Server Editor—if you have a username and a password to start the server, then you can specify those credentials here (as shown in the following screenshot). Twiddle is a JMX library that comes with JBoss, and it is used to access (any) variables that are exposed via the JBoss JMX interfaces. Server publish status A server may have one of the following statuses: Synchronized: Allows you to see if changes are sync (as shown in the follo wing screenshot) Publishing: Allows you to see if changes are being updated Republish: Allows you to see if changes are waiting
Read more
  • 0
  • 0
  • 1799

article-image-creating-web-page-displaying-data-sql-server-2008
Packt
23 Oct 2009
5 min read
Save for later

Creating a Web Page for Displaying Data from SQL Server 2008

Packt
23 Oct 2009
5 min read
This article by Jayaram Krishnaswamy describes how you may connect to SQL Server 2008 and display the retrieved data in a GridView Control on a web page. Trying to establish a connection to the SQL Server 2008 is not possible in Visual Studio 2008 as you will see soon in the tutorial. One way to get around this, as shown in this tutorial, is to create an ODBC connection to the SQL Server and then using the ODBC connection to retrieve the data. Visual Studio 2008 Version: 9.0.21022.8 RTM, Microsoft Windows XP Professional Media Center Edition, and SQL Server 'Katmai' were used for this tutorial. (For more resources on Microsoft, see here.) Connecting to SQL Server 2008 is Not Natively Supported in Microsoft Visual Studio 2008 Designer In the Visual Studio 2008 IDE make a right click on the Data Connections node in the Server Explorer. This will open up the Add Connection window where the default connection being displayed is MS SQL Server Compact. Click on the Change... button which opens the Change Data Source window shown in the next figure. Highlight Microsoft SQL Server as shown and click on the OK button. This once again opens the Add Connection window showing SQL Server 2008 on the machine, Hodentek as shown in the next figure in this case. The connection is set for Windows Authentication and should you test the connectivity you would get 'Success' as a reply. However when you click on the handle for the database name to retrieve a list of databases on this server, you would get a message as shown. Creating a ODBC DSN You will be using the ODBC Data Source Administrator on your desktop to create a ODBC DSN. You access the ODBC Source Administrator from Start | All Programs | Control Panel | Administrative Tools | Data Sources(ODBC). This opens up ODBC Data Source Administrator window as shown in the next figure. Click on System DSN tab and click on the Add... button. This opens up the Create New Data Source window where you scroll down to SQL Server Native Client 10.0. Click on the Finish button. This will bring up the Create a New Data Source to SQL Server window. You must provide a name in the Name box. You also provide a description and click on the drop-down handle for the question, Which SQL Server do you want to connect to? to reveal a number of accessible servers as shown. Highlight SQL Server 2008. Click on the Next button which opens a window where you provide the authentication information. This server uses windows authentication and if your server uses SQL Server authentication you will have to be ready to provide the LoginID and Password. You may accept the default for other configurable options. Click on the Next button which opens a window where you choose the default database to which you want to establish a connection. Click on the Next button which opens a window where you accept the defaults and click on the Finish button. This brings up the final screen, the ODBC Data SQL Server Setup which summarizes the options made as shown. By clicking on the Test Data Source... button you can verify the connectivity. When you click on the OK button you will be taken back to the ODBC Data Source Administrator window where the DSN you created is now added to the list of DSNs on your machine as shown. Retrieving Data from the Server to a Web Page You will be creating an ASP.NET website project. As this version of Visual Studio supports projects in different versions, choose the Net Framework 2.0 as shown. On to the Default.aspx page, drag and drop a GridView control from the Toolkit as shown in this design view. Click on the Smart task handle to reveal the tasks you need to complete this control. Click on the drop-down handle for the Choose Data Source: task as shown in the previous figure. Now click on the <New data Source...> item. This opens the Data Source Configuration Wizard window which displays the various sources from which you may get your data. Click on the Database icon. Now the OK button becomes visible. Click on the OK button. The wizard's next task is to guide you to get the connection information as in the next figure. Click on the New Connection... button. This will take you back to the Add Connection window. Click on the Change... button as shown earlier in the tutorial. In the Change Data Source window, you now highlight the Microsoft ODBC Data Source as shown in the next figure. Click on the OK button. This opens the Add Connection window where you can now point to the ODBC source you created earlier, using the drop-down handle for the Use user or system data source name. You may also test your connection by hitting the Test Connection button. Click on the OK button. This brings the connection information to the wizard's screen as shown in the next figure. Click on the Next button which opens a window in which you have the option to save your connection information to the configuration node of your web.config file. Make sure you read the information on this page. The default connection name has been changed to Conn2k8 as shown. Click on the Next button. This will bring up the screen where you provide a SQL Select statement to retrieve the columns you want. You have three options and here the Specify a custom SQL Statement or stored procedure option is chosen.
Read more
  • 0
  • 0
  • 23962
article-image-cups-how-manage-multiple-printers
Packt
23 Oct 2009
7 min read
Save for later

CUPS: How to Manage Multiple Printers

Packt
23 Oct 2009
7 min read
Configuring Printer Classes By default there are no printer classes set up. You will need to define them. The following are some of the criteria you can use to define printer classes: Printer Type: Printer type can be a PostScript or non-PostScript printer. Location: The location can describe the printer's place; for example the printer is placed on the third floor of the building. Department: Printer classes can also be defined on the basis of the department to which the printer belongs. The printer class might contain several printers that are used in a particular order. CUPS always checks for an available printer in the order in which printers were added to a class. Therefore, if you want a high-speed printer to be accessed first, you would add the high-speed printer to the class before you add a low-speed printer. This way, the high-speed printer can handle as many print requests as possible, and the low-speed printer would be reserved as a backup printer when the high-speed printer is in use. It is not compulsory to add printers in classes. There are a few important tasks that you need to do to manage and configure printer classes. Printer classes can themselves be members of other classes. So it is possible for you to define printer classes for high availability for printing. Once you configure the printer class, you can print to the printer class in the same way that you print to a single printer. Features and Advantages Here are some of the features and advantages of printer classes in CUPS: Even if a printer is a member of a class, it can still be accessed directly by users if you allow it. However, you can make individual printers reject jobs while groups accept them. As the system administrator, you have control over how printers in classes can be used. The replacement of printers within the class can easily be done. Let's understand this with the help of an example. You have a network consisting of seven computers running Linux, all having CUPS installed. You want to change printers assigned to the class. You can remove a printer and add a new one to the class in less than a minute. The entire configuration required is done as all other computers get their default printing routes updated in another 30 seconds. It takes less than one minute for the whole change—less time than a laser printer takes to warm up. A company is having the following type of printers with their policy as: A class for B/W laser printers that anybody can print on A class for draft color printers that anybody can print on, but with restrictions on volume A class for precision color printers that is unblocked only under the administrator's supervision CUPS provide the means for centralizing printers, and users will only have to look for a printer in a single place It provides the means for printing on another Ethernet segment without allowing normal Windows to broadcast traffic to get across and clutter up the network bandwidth It makes sure that the person printing from his desk on the second floor of the other building doesn't get stuck because the departmental printer on the ground floor of this building has run out of paper and his print job has got redirected to the standby printer All of these printers hang off Windows machines, and would be available directly for other computers running under Windows. However, we get the following advantages by providing them through CUPS on a central router: Implicit Class CUPS also supports the special type of printer class called as implicit class. These implicit classes work just like printer classes, but they are created automatically based on the available "printers and printer classes" on the network. CUPS identifies printers with identical configurations intelligently, and has the client machines send their print jobs to the first available printer. If one or more printers go down, the jobs are automatically redirected to the servers that are running, providing fail-safe printing. Managing Printer Classes Through Command-Line You can perform this task only by using the lpadmin -c command. Jobs sent to a printer class are forwarded to the first available printer in the printer class. Adding a Printer to a Class You can run the following command with the –p and -c options to add a printer to a class: $sudo lpadmin –p cupsprinter –c cupsclass The above example shows that the printer cupsprinter has been added to printer class cupsclass: You can verify whether the printers are in a printer class: $lpstat -c cupsclass Removing a Printer from a Class You need to run lpadmin command with –p and –r options to remove printer from a class. If all the printers from a class are removed, then that class can get deleted automatically. $sudo lpadmin –p cupsprinter –r cupsclass The above example shows that the printer cupsprinter has been removed from the printer class, cupsclass: Removing a Class To remove a class, you can run the lpadmin command with the –x option: $sudo lpadmin -x cupsclass The above command will remove cupsclass. Managing Printer Classes Through CUPS Web Interface Like printers, and groups of printers, printer classes can also be managed by the CUPS web interface. In the web interface, CUPS displays a tab called Classes, which has all the options to manage the printer classes. You can get this tab directly by visiting the following URL: http://localhost:631/classes If no classes are defined, then the screen will appear as follows which shows the search and sorting options: Adding a New Printer Class A printer class can be added using the Add Class option in the Administration tab. It is useful to have a helpful description in the Name field to identify your class. You can add the additional information regarding the printer class under the Description field that would be seen by users when they select this printer class for a job. The Location field can be used to help you group a set of printers logically and thus help you identify different classes. In the following figure, we are adding all black and white printers into one printer class. The Members box will be pre-populated with a list of all printers that have been added to CUPS. Select the appropriate printers for your class and it will be ready for use. Once your class is added, you can manage it using the Classes tab. Most of the options here are quite similar to the ones for managing individual printers, as CUPS treats each class as a single entity. In the Classes tab, we can see following options with each printer class: Stop Class Clicking on Stop Class changes the status of all the printers in that class to "stop". When a class is stopped, this option changes to Start Class. This changes the status of all of the printers to "idle". Now, they are once again ready to receive print jobs. Reject Jobs Clicking on Reject Jobs changes the status of all the printers in that class to "reject jobs". When a class is in this state, this option changes to Accept Jobs which changes the status of all of the printers to "accept jobs" so that they are once again ready to accept print jobs.    
Read more
  • 0
  • 0
  • 37004

article-image-technical-best-practices-dynamics-ax-shared-and-aot-object-standards
Packt
23 Oct 2009
15 min read
Save for later

Technical Best Practices for Dynamics AX - Shared and AOT Object Standards

Packt
23 Oct 2009
15 min read
Shared Standards Some Dynamics AX customization best practices are applicable irrespective of AOT element. These standards include X++ standards, naming conventions, label standards, and Help Text guidelines. X++ Standards This section discusses some best practices related to the X++ language. Conformance to this standard results in improved execution time, ease in upgrading and further customization, efficient use of OOP concepts, better readability of code, etc. Some general principles are as follows: Variable or constant or parameter declarations should be as local as possible to utilize memory resources in an efficient way. Error conditions should be checked in the beginning so that minimum work is done for action and rollback of action. This will also hinder denial of service attacks. Denial of service attack is an attempt to stress the system with too many garbage requests so that an authorized user is not served. The parameters supplied as value must not be modified or manipulated as it may increase the chances of using wrong values somewhere else. Code should be written in a clean fashion, which means unused variables, methods, and classes should be removed from the code. The existing MorphX functions or functionality should be used as much as possible (unless other best practices stop you from doing so), rather than creating new ones as it will make upgrading easier. The user should not experience a run-time error. All possible cases should be foreseen and handled accordingly. If some unpredicted case appears during run time, it should show an error in the Infolog with a message to help the users on how to avoid the situation and what action can be taken to prevent it. The value of the this variable should not be changed. The reusability should be maximized. E.g. rather than repeating lines of code at different places, a single method can be written so that changes in the method can be reflected at all the places where this method is used. There should be only one successful return point (except in switch statements) so that object deletion, etc. can be ensured. A method should perform a single well-defined task and be named according to the task performed. Text Constant Standards All the text used in Dynamics AX is supposed to be in a label file irrespective of its use e.g. user interface or error or success message. The use of text constants can be classified into two broad categories i.e. user interface text and system-oriented text. The text used in the user interface should follow the following best practices: Modify property values on the extended data types or base enums inthe application. Never create duplicate label files i.e. the same text (in the same language) but a different label file. New label files can be created when customizing the text, but it is always recommended to reuse the standard labels. However, it may offer a disadvantage—all the changes made to the SYS layer label files will be gone whenever an upgrade occurs. So the decision of customizing an existing label file or creating new label file should be taken carefully. User interface text (labels files) should be used in double quotes. System-oriented text constants must be in single quotes. Exception Handling The principle uses of exception handling include freeing system resources (e.g. memory through object deletion, closing database connection, etc.) and providing constructive information in the Infolog so that the user can prevent such erroneous conditions. The following are a few recommended best practices related to exception handling: A try or catch deadlock or retry loop should always be created around database transactions that can cause deadlocks. In the retry clause the values of transient variables should be set back to the values before try. Branching A few recommended best practices related to the if-else statement and switch statement are as follows: Always use positive logic e.g. write if (true) rather than if (! false). Prefer switch statement rather than multiple if-else statements. Always end a case with a break or return or throw statement unless a fall through mechanism is intentionally used. When a fall through mechanism is used a comment should be given like //fall through so that it is clear to every reader. Code Layout For readability of the code, code should be written in a proper layout. Some chief best practices for code layout are as follows: Remove commented code before shipping code. Follow indentation rules. Follow case rules for naming classes, methods, tables, etc. Methods Following are a few best practices for methods: Methods should be small and logical so that it can be easily overridden or over-layered. Methods should perform a single well defined task and from their name the task performed should be clear. For static class methods and table methods, qualified client, server, or client server should be used in such a way that calls to other tiers are minimized. For greater details refer to the Best Practices for Designing section in the Developer's Guide. To ensure trustworthiness, appropriate access levels (public, private, or protected) should be assigned. Methods should be named according to the Dynamics AX naming conventions; the reserved keywords such as is, check, validate, set, get, and find should be used as per the Dynamics AX way of using these standard methods or functions. All methods using such keywords must not have side effects e.g. no assignment in validate, check, get, or is methods. Parameter's names must start with an underscore (_) character besides following other generalized naming conventions. Handling Dates Dates are sources of error due to variations in date presentation formats and in values due to differences in time zone. A few best practices for handling dates are as follows: Date fields must be stored or displayed in the date field only as IntelliMorph has the ability to display the date value in a format suitable for the user provided that the date format property is chosen as Auto and it is presented in a date control. The system date should not be considered as reliable information but in some cases (e.g. validation of information input by a user) system date should be read using the SystemDateGet() function instead of the today() function. Date conversion should be avoided as it will loose date properties and hence sometimes conversion may result in wrong information. For all user interface-related situations strFmt or date2Str should be used with a value of -1 for all formatting-related parameters. This will allow users to use this information in the format specified in regional settings. Care should also be taken that string variables storing converted date information are sufficiently long. Label Standards It is highly recommended that any user-interface text is defined using labels. This will ensure many advantages during translation. A few label file standards to ensure the true benefits of the label file system are as follows: The location of label files should be the most generalized one i.e. extended data type (EDT). In some cases an existing EDT cannot be used only because of the difference in label text. In such cases a new EDT should be created by extending the existing EDT. In such cases other alternatives may also be available (e.g. label change at the field) but the rule of thumb is to use the label at the most general place. The label files should not be duplicated i.e. two label files should not exist for the same text. AOT Object Standards The AOT object standards are specific to a particular AOT element. Broadly we can classify AOT elements as follows: Data Dictionary Extended data type Base Enum Tables Feature keys Table collection Classes Forms Reports Jobs Menu items Data Dictionary This is a group of AOT objects including the items mentioned in the previous section. The best practices for tables can further be divided into best practices for the fields, field groups, indexes, table relations, delete actions, and methods. Extended Data Type The EDT plays a great role as it is the basic entity of GUI elements. The following are a few basic best practices related to extended data types. All date and date format-related properties should be set to Auto. Help text should not be same as the label property. Help text is supposed to be more descriptive and should be able to explain why and/or how. An EDT name must be a real-world name, prefixed with module (if it belongs to one module only). Base Enum The following are a few basic best practices related to Base Enum: The Enum name should be an indication of either the few possible values or type of values. For example DiscountType, OpenClose, etc. Display length property should be set to auto so that in every language the full name can be displayed. Help and label properties must have some value. Help and label properties should not have the same value. Tables Many of the best practices for tables come under the scope of performance optimization, database design standards, etc. and hence those standards have been discussed elsewhere. Some of the standards not discussed are discussed here. The table name may consist of the following valuable information: Prefix: Module name such as Cust for Account Payable, Sales for Account Receivables Infix: Logical description of the content Post fix: Type of data e.g. Trans (for transactions), Jour (Journals), Line (table containing detailed information about a particular record in header table), Table (primary main tables), Group, Parameters, Setup, or module name to which the table belongs Label is a mandatory property and tables must be labelled using Label ID only. The text value of Label ID must be unique in all languages supported. If a table belongs to one of the four types Parameter, Group, Main, or WorksheetHeader, then it must have an associated form to maintain the table records. This form should have a name identical to its display menu item (used to start this form) and like the table name. formRef is the property of a table for the name of the associated form. Title Field 1 and Title Field 2 should be mentioned: TitleField1: The key field for the records in the table. This should be a descriptive title, if the key is information for the user. TitleField2: The description for the records in the table. Fields Most of the properties for the fields are inherited from extended data types; however, it is not mandatory to use some or all inherited values for such properties. Here are a few guidelines: Name: Should be like the corresponding EDT name but if named separately, it should be logical. The fields used as key should be postfixed as ID e.g. CustId, ItemId, etc. HelpText: This is a mandatory property and inherited from the corresponding EDT. Since Help Text needs to be customized as per the different uses ofthe same EDT, Help text can be modified at any field but the following arethe guidelines: The help text property should not be same as the label property. Label is also a mandatory property, which is inherited from EDT. If a value is set here, it should be different from the value on EDT. Every field that is either the primary key or one of the key mandatory properties must be set to Yes. Before considering memo or container type fields, it should be kept in mind that they add time to application and database fetch, they inhibit array fetching, and these types of fields cannot be used in where expressions. Field Group The field group is a group of fields shown in the user interface. Dynamics AX has some standard groups (e.g. Identification, Administration, Address, Dimension, Setup, Misc, etc.), while other can be created. The fields that logically belong together can be placed in one field group while the Misc field group can be used to group fields that do not fit in any other field group. The dimension field group must have a single kind of field Dimension. The field groups should have the same kind of grouping at the database and form or reports to improve caching and hence the performance. Delete Actions The database integrity is one of the key principles in Relational Database Management System (RDBMS). The delete action should be used on every relation between two tables. The following are key best practices for delete actions. Use a delete action on every relation between two tables. Use table delete actions instead of writing code to specify whether deletes are restricted or cascaded. Dynamics AX has three types of delete actions; selection of one will solely depend upon the custom requirements. Table Methods The tables in Dynamics AX have several properties such as delete, validateDelete, etc. and hence Dynamics AX recommends that you should not write methods or X++ code to implement something that can be done just by setting property values. Dynamics AX recommends using inbuilt table methods for those custom requirements that cannot be met with table properties settings. Some of the table methods are mandatory to implement e.g. find and exists methods. Classes The classes have a peculiarity that they may have both a back end (database) and front end (GUI). The front interface should be easy to use and at the same time as secure as possible. The implementation details of the class should always be hidden from the user and hence use of private or protected methods is recommended. The back-end methods are highly secure, standardized, and reliable and hence use of private or protected methods is recommended in prescribed design patterns. The design patterns depend upon the type of class. Classes can be categorized in the following categories: Real object Action class Supporting class The following are a few common best practices related to declaration: Object member variables must only be used to hold the state of the object i.e. variables for which values should be kept between and outside instance method calls. Use of global variables must be minimized. Unused variables must be cleaned up; a tool available at Add-Ins | Best Practices | Check Variables can be used to know the unused variables. Constants used in more than one method in a class (or in subclass) should be declared during class declaration. There is a rich set of best practices for classes and the Best Practices for Microsoft Dynamics AX Development released by Microsoft would be good read. Forms The forms are in the presentation tier in any three-tier architecture system. Most of them are related to look and feel or layout. Some other best practices for forms revolve around the following characteristics: Use of Intellimorph maximally No forced date or time format No forced layout such as fixed width for label, position control for GUI controls, etc. Use of label files for GUI text Forms having minimal coding Avoid Coding on Forms The basic concept of three-tier architecture is that forms should be used only for the presentation tier and hence no other code such as business logic should be there on forms. The code placed on forms also reduces their reusability and the ease of further customization; e.g. if you want to develop an enterprise portal, the code written on forms will have to be written again in classes or table methods, etc., which will make the implementation complex. Another example may be when you want to 'COM enable' your business logic; form code related to business logic will make your life almost impossible. Any code (other than presentation logic) written on forms imposes limitation on performance as call between two different layers increase slowing the performance and hence code on forms should be avoided as much as possible. In cases where avoiding code on forms is not possible the guidelines summarized in the following table should be used for writing code on forms. Place to Write Code Guidelines Form level When code is related to whole form When code is related to multiple data sources Editor or Display methods (only those that are not related to any data source) Data source Data source-related Edit or Display methods Code related only to the data source that cannot be effectively placed in a table method Controls When it is strictly related to the controls Use of IntelliMorph Maximally Due to a user's locale or preferred format a form may be presented in a different language and/or a different date, time, or currency format. Dynamics AX best practices recommend Auto as the value for the display properties related to the following: Date Currency Time Language Number format (such as decimal operator, separator, etc.) Label size Form size The rule of thumb is to keep the various properties as Auto or default value, which will help IntelliMorph to function maximally. For further details about best practices readers are recommended to go through the Developers Guide for Best Practices. Reports The peculiar fact about the reports is that they are output media where the external environment such as paper size, user's configuration about the locale or language, font size, etc. matters. Dynamics AX recommends using 'Auto Design' to develop the report as these kinds of reports can change the layout according to external environmental variables. Another way to develop a report in Dynamics AX is 'Generated Design'; this type of design is recommended only when strict report layout is required. A few such examples may be regulatory reports, accounts reports, etc. Summary In this two part article we discussed various areas where quality could be improved by adopting best practices. We also discussed various best practices, theory behind best practices, and how to adopt these best practices, i.e. with practical tips.
Read more
  • 0
  • 0
  • 9945
Modal Close icon
Modal Close icon