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-installation-and-basic-features-enterprisedb
Packt
24 Oct 2009
3 min read
Save for later

Installation and basic features of EnterpriseDB

Packt
24 Oct 2009
3 min read
Installing the EnterpriseDB Download PostgrePlus Advanced Server 8.3 ( pgplus-advsvr-windows-83012b.exe (120MB) ) from the following site: http://www.enterprisedb.com/products/download.do. After downloading the program double click the executable file. You may need to choose a language from a list of languages. Here English has been chosen. The welcome window gets displayed as shown. Click Next. Choose the option you need. Read notes on this page to make the choice. Here, the Oracle compatibility has been chosen. Click Next or, choose a different location by browsing. Here the default location is accepted. Click Next. The window that shows up displays all the various features that are available. Pick and choose the features. Here all features are chosen. Click Next. The next window shows the links from where the JDBC drivers for connecting to Oracle and MySQL are available displayed. Click Next . In the window that shows up you need to choose the password for the Operating System UserID and Password. Read the cautionary remarks on this page. Choose Next. At this point your anti-virus program may require you to permit to run the program. McAfee is the anti-virus program on this computer. In the window that gets displayed you may need to choose the administrator's log in credentials. You may also Browse and select the Data Destination Directory. Herein the default is accepted. Click Next. In the windows that gets displayed you may choose the type of environment for which the server will be used as well as the work load for which you may be using the server. The dynamic tuning options available are: Server Utilization Development: This is a development machine and many other applications will be running on it. Stress testing should not be performed with this configuration. EnterpriseDB will use a minimal amount of memory. Mixed: Several applications will be running on this machine. Choose this option for web/application servers. Dedicated: This machine is dedicated to run EnterpriseDB and will use available memory to optimize performance. The Workload Profile Transaction Processing: The running application is a transaction intensive applications. General Purpose: The database will be used for transaction processing as well as complex queries and reporting. Reporting: The database will be used for reporting applications. For this tutorial, the Mixed option for Server Utilization and General Purpose for Workload Profile were chosen. Click on Next. The Summary page gets displayed showing all the options chosen. Click on the Install button. The window with a progress bar gets displayed. You may get a warning from the anti-virus program on your computer to allow the file to be executed. Click OK to allow install.
Read more
  • 0
  • 0
  • 2302

article-image-visual-etl-development-ibm-datastage
Packt
24 Oct 2009
4 min read
Save for later

Visual ETL Development With IBM DataStage

Packt
24 Oct 2009
4 min read
You use Designer, one of the DataStage clients, for ETL jobs development. When you start Designer, in addition to entering your host system and credential, you must also specify the project you’d like to work on. A DataStage project stores jobs and define their environment, such as their security and execution resources. Your project, as well as your user account, is typically created by your DataStage administrator. To develop a new job, on the icon toolbar, click the drop-down arrow to the right of the New icon (I circle in red). We’ll develop a parallel job, so click the Parallel Job from the drop-down list. In DataStage, a parallel job can execute in parallel mode (in simple terms, this means the job does not process its data records sequentially, one record after another). We can now start to design our job in the job canvas. For now, our parallel job name is Untitled 1, as shown on the canvas title. Our job extracts its input data from a customer sequential file, transforms the data, and then loads it into an Oracle table. The customer file contains new customers and name changes of the existing customers. The customer file has more data (more columns) than we need; we’ll extract only those we need. In DataStage, you build a job by selecting and linking stages on the job canvas. So, on the Palette, click File, look for Sequential File stage by clicking the up or down arrow. Drag and drop our first stage, the Sequential File stage, from the Palette to the left side of the canvas. We’d like to layout our stages left to right to visualize them processing data in that direction, so we start placing the input stage on the left of the canvas (we can move stages around the canvas, though, by dragging them). Rename the Sequential File stage to Customer by selecting (clicking) and clicking it again, and typing over the default name (Sequential_File_1). Next, add Transformer stage (under Processing palette) and Oracle Enterprise stage (under Database palette) that we need for our job. Rename them as shown. We use the Transformer stage to change (transform) customer names to uppercase. Now that we have the stages we need for our job, we’ll link them together. Right click the Customer stage, hold and drag & drop on the Uppercase stage, and then, from Uppercase stage to the Customer_Dim stage. You can rename the links just like the way you rename stages. Just in case something happens to our system, we’d like to save our works so far. Name the job Load_Customer_Dim and you can choose the folder (called Category in DataStage) of your choice where you want to put the job. Notice the canvas title now reflects the name of our parallel job (changes from its default name given when we’re creating it). The Customer stage has a warning sign (the yellow! sign), which indicates that it has an error. This is because we haven’t specified its parameters. For example, the file it refers to. So, let’s fix it. Double-click the Customer stage. On the Properties tab select the File property, and type in the file name including its full path. The sequential file must be accessible by the DataStage server. Next, we need to specify the format of our file. For example, set the Record level’s Final delimiter and Field default’s Delimiter as shown. We must also specify the record layout, i.e. its fields (columns). To test that the stage will be able to read the data as specified, click the View Data button (upper right hand corner). You can specify the number of rows (records) you’d like to view. When you click OK and you have set the correct specification for the file, you’d see the data. When you finish viewing the data, close the view window as well as the property window. We’re done with the Customer stage.
Read more
  • 0
  • 0
  • 3665

article-image-custom-data-readers-ext-js
Packt
24 Oct 2009
9 min read
Save for later

Custom Data Readers in Ext JS

Packt
24 Oct 2009
9 min read
When writing Chapter 12, "It's All about the Data," of Learning Ext JS, I switched things up a bit and switched the server-side processes to utilizing Adobe's ColdFusion application server, instead of the PHP we had been using in the rest of the book. There were a few reasons we decided to do this. To show that Ext JS can work with any server-side technology. ColdFusion 8 includes Ext JS 1.1 for it's new Ajax form components. Adobe uses a custom format for the serialized JSON return of query data, making it perfect for our example needs. I'm a ColdFusion programmer. Some time ago, before writing Chapter 12, I had begun to use a Custom Data Reader that I had found on the Ext JS forums. Another Ext user and ColdFusion programmer, John Wilson, had written the custom reader to consume Adobe's custom JSON return for queries. First, let me show you why Adobe's format differs from the generally expected serialized JSON return of a query. Here's an example of a typical query response. { 'results': 2, 'rows': [ { 'id': 1, 'firstname': 'Bill', occupation: 'Gardener' }, // a row object { 'id': 2, 'firstname': 'Ben' , occupation: 'Horticulturalist' } // another row object ] } And here's an example of how ColdFusion returns a query response.     {        "COLUMNS":["INTPROPERTIESID","STRDEVELOPMENT","INTADDRESSID", "STRSTREET","STRSTREET2", "STRCITY","CHSTATEID","INTZIP"],        "DATA":[            [2,"Abbey Road",6,"456 Abbey Road","Villa 5","New York","NY",12345],            [6,"Splash",39,"566 aroundthe bend dr",null,"Nashville","TN",37221]        ]    } You can see, when examining the two formats that they are very divergent. The typical format returns an array of row objects of the query's results, whereas ColdFusion's format is an array (DATA) of arrays (each row of the query result), with each row array only containing the data. The ColdFusion format has extracted the column names into it's own array (COLUMNS), as opposed to the name/value pairing found in the object notation of the typical return. It's actually very smart, on Adobe's part, to return the data in this fashion, as it would ultimately mean smaller data sets returned from a remote call, especially with large recordsets. John's CFJsonReader, a custom data reader and an extended component of Ext's base DataReader, was able to translate ColdFusion's data returns by properly parsing the JSON return into Records of an Ext Store. It worked fairly well, with a few minor exceptions. it didn't handle the column aliasing you could do with any other Ext JS data reader (name:'development',mapping:'STRDEVELOPMENT') it didn't allow data type association with a value, as other Ext JS data readers (INTZIP is of type 'int', STRDEVELOPMENT is of type 'string', etc) So, it worked, but ultimately was limited. When I was writing Chapter 13, "Code for Reuse: Extending Ext JS", I really dove into extending existing Ext JS components. This helped me gain a better understanding of what John had done, when writing CFJsonReader. But, after really reviewing the code, I saw there was a better way of handling ColdFusion's JSON return. What it basically came down to was that John was extending Ext's base DataReader object, and then hand parsing almost the entire return. Looking at the above examples, you'll notice that Adobe's implementation is an array of arrays, rather than an array of objects. Ext JS already comes with an ArrayReader object, so I knew that by writing a custom data reader that extended it I would be able to get the desired results. Half an hour later, I had "built a better mousetrap" and we now have a Custom Data Reader for properly parsing ColdFusion's JSON return, without the previous limitations. /* * Ext JS Library 2.0 * Copyright(c) 2006-2007, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license * ******************************************* * Steve 'Cutter' Blades (CutterBl) no.junkATcutterscrossingDOTcom * http://blog.cutterscrossing.com * * Inspired by the CFJsonReader, originally writtin by John Wilson (Daemach) * http://extjs.com/forum/showthread.php?t=21408&highlight=cfjsonreader * * This Custom Data Reader will take the JSON return of a ColdFusion * Query object, rather returned straight up, or via the ColdFusion * QueryForGrid() method. * * The CFQueryReader constructor takes two arguments * @meta : object containing single key/value pair for the 'id' of each record * @recordType : field mapping object * * The recordType object allows you to alias the returned ColdFusion column * name (which is always passed in upper case) to any 'name' you wish, as * well as assign a data type, which your ExtJS app will attempt to cast * whenever the value is referenced. * * ColdFusion's JSON return, for a ColdFusion Query object, will appear in the * following format: * * {"COLUMNS":["INTVENDORTYPEID","STRVENDORTYPE","INTEXPENSECATEGORIESID", * "STREXPENSECATEGORIES"],"DATA" :[[2,"Carpet Cleaning",1,"Cleaining"], * [1,"Cleaning Service",1,"Cleaining"]]} * * The ColdFusion JSON return on any query that is first passed through * ColdFusion's QueryForGrid() method will return the object in the * following format: * * {"TOTALROWCOUNT":3, "QUERY":{"COLUMNS":["MYIDFIELD","DATA1","DATA2"], * "DATA":[[1,"Bob","Smith"],[6,"Jim","Brown"]]}} * * The Ext.data.CFQueryReader is designed to accomodate either format * automatically. You would create your reader instance in much the same * way as the CFJsonReader was created: * * var myDataModel = [ * {name: 'myIdField', mapping: 'MYIDFIELD'}, * {name: 'data1', mapping: 'DATA1'}, * {name: 'data2', mapping: 'DATA2'} * ]; * * var myCFReader = new Ext.data.CFJsonReader({id:'myIdField'},myDataModel); * * Notice that the 'id' value mirrors the alias 'name' of the record's field. */ Ext.data.CFQueryReader = function(meta, recordType){ this.meta = meta || {}; Ext.data.CFQueryReader.superclass.constructor.call(this, meta, recordType || meta.fields); }; Ext.extend(Ext.data.CFQueryReader, Ext.data.ArrayReader, { read : function(response){ var json = response.responseText; var o = eval("("+json+")"); if(!o) { throw {message: "JsonReader.read: Json object not found"}; } if(o.TOTALROWCOUNT){ this.totalRowCount = o.TOTALROWCOUNT; } return this.readRecords(((o.QUERY)? o.QUERY : o)); }, readRecords : function(o){ var sid = this.meta ? this.meta.id : null; var recordType = this.recordType, fields = recordType.prototype.fields; var records = []; var root = o.DATA; // give sid an integer value that equates to it's mapping sid = fields.indexOfKey(sid); // re-assign the mappings to line up with the column position // in the returned json response for(var a = 0; a < o.COLUMNS.length; a++){ for(var b = 0; b < fields.length; b++){ if(fields.items[b].mapping == o.COLUMNS[a]){ fields.items[b].mapping = a; } } } for(var i = 0; i < root.length; i++){ var n = root[i]; var values = {}; var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null); for(var j = 0, jlen = fields.length; j < jlen; j++){ var f = fields.items[j]; var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j; var v = n[k] !== undefined ? n[k] : f.defaultValue; v = f.convert(v, n); values[f.name] = v; } var record = new recordType(values, id); record.json = n; records[records.length] = record; } if(!this.totalRowCount){ this.totalRowCount = records.length; } return { records : records, totalRecords : this.totalRowCount }; } }); So, this changes our examples for Chapter 12 just a little bit. First of all, we'll need to have the CFQueryReader included, in place of the CFJsonReader. You can change the script tags in the samples for Examples 3 and 4. ... <script language="javascript" type="text/javascript" src="/scripts/custom-ext/CFQueryReader.js"></script> ... Next, we'll change the scripts for these two examples. We'll remove our configuration references for CFJsonReader, and replace them with the updated configuration for the CFQueryReader. /* * Chapter 12 Example 3 * Data Store from custom reader * * Revised: SGB (Cutter): 12.17.08 * Replaced CFJsonReader with CFQueryReader */ // Save all processing until the // DOM is completely loaded Ext.onReady(function(){ var ourStore = new Ext.data.Store({ url:'Chapter12Example.cfc', baseParams:{ method: 'getFileInfoByPath', returnFormat: 'JSON', queryFormat: 'column', startPath: '/images/' }, reader: new Ext.data.CFQueryReader({ id: 'NAME', // This is supposed to match the 'mapping' fields:[ {name:'file_name',mapping:'NAME'}, {name:'file_size',mapping:'SIZE'}, {name:'type',mapping:'TYPE'}, {name:'lastmod',mapping:'DATELASTMODIFIED'}, {name:'file_attributes',mapping:'ATTRIBUTES'}, {name:'mode',mapping:'MODE'}, {name:'directory',mapping:'DIRECTORY'} ] }), fields: recordModel, listeners:{ beforeload:{ fn: function(store, options){ if (options.startPath && (options.startPath.length > 0)){ store.baseParams.startPath = options.startPath; } }, scope:this }, load: { fn: function(store,records,options){ console.log(records); } }, scope:this } }); ourStore.load(); }); /* * Chapter 12 Example 4 * Data Store from custom reader - Filtering * * Revised: SGB (Cutter): 12.17.08 * Replaced CFJsonReader with CFQueryReader */ // Simple function/object to 'clone' objects cloneConfig = function (config) { for (i in config) { if (typeof config[i] == 'object') { this[i] = new cloneConfig(config[i]); } else this[i] = config[i]; } } // Save all processing until the // DOM is completely loaded Ext.onReady(function(){ var initialBaseParams = { method: 'getDirectoryContents', returnFormat: 'JSON', queryFormat: 'column', startPath: '/testdocs/' }; var ourStore = new Ext.data.Store({ url:'Chapter12Example.cfc', baseParams: new cloneConfig(initialBaseParams), reader: new Ext.data.CFQueryReader({ id: 'NAME', // This is supposed to match the 'mapping' fields:[ {name:'file_name',mapping:'NAME'}, {name:'file_size',mapping:'SIZE'}, {name:'type',mapping:'TYPE'}, {name:'lastmod',mapping:'DATELASTMODIFIED'}, {name:'file_attributes',mapping:'ATTRIBUTES'}, {name:'mode',mapping:'MODE'}, {name:'directory',mapping:'DIRECTORY'} ] }), listeners:{ beforeload:{ fn: function(store, options){ for(var i in options){ if(options[i].length > 0){ store.baseParams[i] = options[i]; } } }, scope:this }, load: { fn: function(store, records, options){ console.log(records); }, scope: this }, update: { fn: function(store, record, operation){ switch (operation){ case Ext.record.EDIT: // Do something with the edited record break; case Ext.record.REJECT: // Do something with the rejected record break; case Ext.record.COMMIT: // Do something with the committed record break; } }, scope:this } } }); ourStore.load({recurse:true}); filterStoreByType = function (type){ ourStore.load({dirFilter:type}); } filterStoreByFileType = function (fileType){ ourStore.load({fileFilter:fileType}); } clearFilters = function (){ ourStore.baseParams = new cloneConfig(initialBaseParams); ourStore.load(); } }); Summary These very basic changes have no overall effect on our examples. They function exactly as they did before. The new Custom Data Reader loads the data, returned from ColdFusion, exactly as it should. Now, we can also work with these data stores in the same manor as we would with any other data store set up through Ext JS, having the ability to alias columns, define field data types, and more.
Read more
  • 0
  • 0
  • 5023

article-image-creating-and-managing-user-groups-joomla-and-virtuemart
Packt
24 Oct 2009
9 min read
Save for later

Creating and Managing User Groups in Joomla! and VirtueMart

Packt
24 Oct 2009
9 min read
User manager In Joomla!, there is one User Manager component from where you can manage the users of that site. However, for the VirtueMart component, there is another  user manager which should be used for the VirtueMart shop. To be clear about  the differences of these two user managers, let us look into both. Joomla! user manager Let us first try Joomla!'s user manager. Go to the Joomla! control panel and click on the User Manager icon or click on Site | User Manager. This brings the User Manager screen of Joomla!: We see that the users registered to the Joomla! site are listed in this screen. This screen shows the username, full name, enabled status, group that the user is assigned to, email of the user, date and time when they last visited, and user ID. From this screen, you may guess that any user can be enabled or disabled by clicking on the icon in the Enabled column. Enabled user accounts show a green tick mark in the Enabled column. For viewing the details of any user, click on that user's name in the Name column. That brings up the User:[Edit] screen: As you see, the User Details section shows some important information about the user including Name, Username, E-mail, Group, and so on. You can edit and change these settings including the password. In the Group selection box, you must select one level. The deepest level gets the highest permission in the system. From this section, you can also block a user and decide whether they will receive system  emails or not. In the Parameters section, you can choose the Front-end Language and Time Zone for that user. If you have created contact items using Joomla!'s Contacts component, you may assign one contact to this user in the Contact Information section. VirtueMart user manager Let us now look into VirtueMart's user manager. From the Joomla! control panel, select Components | VirtueMart to reach the VirtueMart Administration Panel. To view the list of the user's registered to the VirtueMart store, click on Admin | Users. This brings the User List screen: As you can see, the User List screen shows the list of users registered to the shop. The screen shows their username, full name, group the user is assigned to, and their shopper group. In the Group column, note that there are two groups mentioned. One group is without brackets and another is inside brackets. The group name mentioned inside brackets is Joomla!'s standard user groups, whereas the one without brackets is VirtueMart's user group. We are going to learn about these user groups in the  next section. For viewing the details of a user, click on the user's name in Username column. That brings the Add/Update User Information screen: The screen has three tabs: General User Information, Shopper Information, and Order List. The General User Information tab contains the same information which was shown in Joomla!'s user manager's User: [Edit] screen. The Shopper Information tab contains shop related information for the user: The Shopper Information section contains: a vendor to which the user is registered the user group the user belongs to a customer number/ID the shopper group Other sections in this tab are: Shipping Addresses, Bill To Information, Bank Account, and any other section you have added to the user registration or account maintenance form. These sections contain fields which are either available on the registration or account maintenance form. If the user has placed some orders, the Order List tab will list the orders placed by that user. If no order has been placed,  the Order List tab will not be visible. Which user manager should we use? As we can see, there is a difference between Joomla!'s user manager and VirtueMart's user manager. VirtueMart's user manager shows some additional information fields, which are necessary for the operation of the shop. Therefore, whenever you are managing users for your shop, use the user manager in the VirtueMart component, not Joomla!'s user manager. Otherwise, all customer information will not be added or updated. This may create some problems in operating the VirtueMart store. User Groups Do you want to decide who can do what in your shop? There is a very good way for doing that in Joomla! and VirtueMart. Both Joomla! and VirtueMart have some predefined user groups. In both cases, you can create additional groups and assign permission levels to these groups. When users register to your site, you assign them to one of the user groups. Joomla! user groups Let us first look into Joomla! user groups. Predefined groups in Joomla! are  described below: User Group Permissions Public Frontend Registered Users in this group can login to the Joomla! site and view the contents, sections, categories, and the items which are marked only for registered users. This group has no access to content management. Author Users in this group get all the permissions the Registered group has. In addition to that, users in this group can submit articles for publishing, and can edit their own articles. Editor Users of this group have all the above permissions, and also can edit articles submitted by other users. However, they cannot publish the contents. Publisher Users in this group can login to the system and submit, edit, and publish their own content as well as contents submitted by other users. Public Backend Manager Users in this group can login to the administration panel and manage content items including articles, sections, categories, links, and so on. They cannot manage users, install modules or components, manage templates and languages, and access global configurations. Users in this group can access some of the components for which the administrator has given permission. Administrator In addition to content management, users in this group can add a user to Super Administrator group, edit a user, access the global configuration settings, access the mail function, and manage/install templates and language files. Super Administrator Users in this group can access all administration functions. For every site, at least one should be in this group to perform global configurations. You cannot delete a user in this group or move him/her to another group. As you can see, most of the users registering to your site should be assigned to the Registered group. By default, Joomla! assigns all newly registered users to the Registered group. You need to add some users to the Editor or Publisher group if they need to add or publish content to the site. The persons who are managing the shop should be assigned to other Public Backend groups such as Manager, Administrator or Super Administrator. VirtueMart user groups Let us now look into the user groups in VirtueMart. To see the user groups, go to VirtueMart's administration panel and click on Admin | User Groups. This shows the User Group List screen: By default, you will see four user groups: admin, storeadmin, shopper, and demo. These groups are used for assigning permissions to users. Also, note the values in the User Group Level column. The higher the value in this field, the lower the permissions assumed for the group. The admin group has a level value of 0, which means it has all of the permissions, and of course, more than the next group storeadmin. Similarly, storeadmin group has more permissions than the shopper group. These predefined groups are key groups in VirtueMart, and you cannot modify or delete these groups. These groups have the following permissions: Group Permissions admin This group has permissions to use all of the modules except checkout and shop. The admin group does not need these because admin users usually do not shop in their store. storeadmin This group has fewer permissions than admin group. Users in this group can access all the modules except the admin, vendor, shop, and checkout modules. They cannot set the global configurations for the store, but can add and edit payment methods, products, categories, and so on. shopper This group has the least permission among the three key groups. By default, users registered to the shop are assigned to this group. Users in this group can fully access the account module, and can use some functions of the shop, coupon, and checkout modules. demo This is a demo group created by default so that administrators can test and play with it. For most of the shops, these four predefined groups will be enough to implement appropriate permissions. However, in some cases you may need to create a new user group and assign separate permissions to that group. For example, you may want to employ some people as store managers who will add products to the catalog and manage the orders. They cannot add or edit payment methods, shipping methods, or other settings, except product and orders. If you add these people to the storeadmin group then they get more permissions than required. In such situations, a good solution is to create a new group, add selected user accounts to that group, and assign permissions to that group. Creating a new user group For creating a new user group, click on the New button in the toolbar on the User Group List screen. This brings Add/Edit a User Group screen: In the Add/Edit a User Group screen, enter the group's name and group level. You must type a higher value than existing groups (for example, 1000). Click on the Save icon to save the user group. You will now see the newly created user group in the User Group List screen.
Read more
  • 0
  • 0
  • 8734

article-image-working-sbs-services-user-part-1
Packt
23 Oct 2009
6 min read
Save for later

Working with SBS Services as a User: Part 1

Packt
23 Oct 2009
6 min read
E-mail, Calendar, and Contacts SBS 2008 includes Exchange 2007, which provides E-mail, Calendar, and Contact functionality. This is available through Outlook, over the Web via Outlook Web Access and on mobile devices. If the user makes a change to one, it will be replicated to Exchange and then to the other locations. How to access from the other locations will be covered later in this article. I'm going to presume that you understand how to send and read email and create and use contacts, but I will share some useful scenarios that many small businesses benefit from, but don't always understand are present in SBS 2008. Some of these will rely on Office 2007 with Outlook, while others can be seen via the web-based interface too. The scenarios are: Viewing your calendar and other people's calendars Scheduling a meeting for multiple people and ensuring their diaries are all free for the time period Telling people when you are going to be away or unavailable Finding emails that have been filed Recovering emails that have been deleted and removed from the deleted items folder All of the actions in this section are carried out on a user's computer, logged in as that user. Only where SBS 2008 is explicitly mentioned, is there an action that is carried out on the server. Outlook 2003 and 2007 connection configuration To configure Microsoft Outlook 2007, you should simply have to open Outlook as it should auto-configure itself. Outlook 2003 will require configuring, but I'm only going cover the important sections here. For full instructions, click on the link How do I use Outlook Anywhere, on the Remote Web Workplace main screen. The links on Remote Web Workplace point to addresses that begin with https://sites/..., which is not accessible from outside the SBS 2008 network. This should be changed to https://remote.yourdomain.co.uk/... as described later in this article. If this has not been done and a user needs access to the information, then they can edit the address in their browser replacing the first part of the URL as described above. If you need to manually configure Outlook, you will need to select the server as an Exchange server. The name of the Microsoft Exchange Server is the name of your SBS 2008 server. In the following screenshot, the name of my SBS 2008 server is davidoverserver and this is entered into the Microsoft Exchange Server section, along with the User Name of the user I am logged in as on their computer. You can either click on Next to finish the settings, or if this is a laptop or a machine that may access SBS 2008 from a remote location, click on More Settings. Click on the Connection tab and then put a check mark in the Connect to my Exchange mailbox using HTTP check box. Finally, click the button Exchange Proxy Settings. Once the proxy settings are open, you will need to type in the remote access URL for your server and also check the Mutually authenticate the session when connecting with SSL, and then enter the name of your remote access server, preceded by msstd:. Clicking on OK will enable you to finish the configuration. Once these changes have been enabled, Outlook will connect to the network without any further action—provided you have an Internet connection, and should work offline until it gets an Internet connection. Calendar management SBS 2008 provides each user a calendar that they can use to manage their diary and which they can choose to share with colleagues if they desire. The level of details shared can be from very basic free and busy time slots through to enabling someone else to have the ability to see and change the diary. This availability of information does concern some users, which is why they can also mark any appointment as private and no details will be shared with others, even if the calendar has been fully shared. Outlook on the desktop enables access to both your and other's calendars, while Outlook and Windows Mobile devices offer much less, if any, access to other people's calendars. I will only describe each task from Outlook in this section, and will provide more information on using Outlook Web Access later in this article. Viewing Calendars Start Outlook from the Start menu. Once Outlook has loaded, click on the Calendar button or go to the Go menu and select Calendar from the menu. You will see your calendar displayed, normally in the Day format with today showing. In the example below, you can see the padlock for the private appointment that others can't see, two normal appointments, and the tentative appointment that is not confirmed at 17:00. To open another person's calendar, click the Open a Shared Calendar link on the lefthand side and then type in the name of the person whose calendar you want to see. If you have permission to view their calendar, you will see both calendars side by side as follows: If you do not have permission and you are running Outlook 2007, you will be prompted to send an email requesting permission. The email will look like this: If the person receiving this email has Outlook 2007, they simply click on Accept to enable you to view the calendar. If you or they have an earlier version of Outlook, then the person whose calendar you want to view will need to carry this task out by hand. To do this, get that individual to open Outlook and then their Calendar and right-click on Calendar under My Calendars and then select Properties from the menu. When the properties appear, go to the Permissions tab and either add the user and assign specific permission, or to make life easier, simply set the default access to reviewer. You can now view both your and other's calendars to identify opportunities to meet. You can open more than one other person's calendar, but things can get confusing with so many open. With Office 2007, you can overlay the calendars by clicking the arrow next to someone's name. For all versions of Outlook, you close a calendar by removing the check mark next to their name in the lefthand navigation pane.
Read more
  • 0
  • 0
  • 3045

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-customizing-default-theme-drupal
Packt
23 Oct 2009
3 min read
Save for later

Customizing the Default Theme in Drupal

Packt
23 Oct 2009
3 min read
Let's look at the default theme (garland) and customize it. We can customize the following features: Color scheme, either based on a color set, or by changing the individual colors If certain elements, such as the logo, are displayed The logo The favicon Back in the Themes section of the Administer area, there is a configure link next to each theme; if we click this we are taken to the theme's configuration page. Although Doug ideally wants a new theme that is unique to his website, he also wants to have a look at a few different options for the default theme. In particular, he wants to add his company's logo to the website and try a number of red color schemes as those are his corporate colors. Color Scheme The color scheme settings are quite intuitive and easy to change. We can either: Select a color set Change each color by entering the hexadecimal color codes (the # followed by 6 characters) Select the colors from the color wheel To change a color using the color wheel, we need to click on the color type (base color, link color, etc.) to select it and then chose the general color from the wheel and the shade of the color from the square within. When we change the colors or color set, the preview window below the settings automatically updates to reflect the color change. The following color sets are available: Blue Lagoon (the default set) Ash Aquamarine Belgian Chocolate Bluemarine Citrus Blast Cold Day Greenbeam Meditarrano Mercury Nocturnal Olivia Pink Plastic Shiny Tomato Teal Top Custom Quite a number of these are red-based color schemes, let's look into them, they are: Belgian Chocolate Meditarrano Shiny Tomato Belgian Chocolate Color Set The Belgian Chocolate color set uses a dark red header with a gradient starting with black flowing into a dark red color. The page's background is a cream color and the main content area has a white background as illustrated by the picture below: Mediterrano Color Set The Mediterrano color set uses a lighter red color where the gradient in the header starts with a light orange color which then flows into a light red color. Similar to the Belgian Chocolate color scheme the background is cream in color with a white background for the content area. Shiny Tomato Color Set The Shiny Tomato color set has a gradient header that starts with deep red and flows into a bright red color. The page's background is light grey with white background for the main content area, reflecting a professional image. The Shiny Tomato color set uses a red scheme which is in Doug's logo and he feels this set is the most professional of the three and wants us to use that.  
Read more
  • 0
  • 0
  • 1733

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-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-configuring-and-securing-python-ldap-applications-part-2
Packt
23 Oct 2009
14 min read
Save for later

Configuring and securing PYTHON LDAP Applications Part 2

Packt
23 Oct 2009
14 min read
This is the second article in the article mini-series on Python LDAP applications by Matt Butcher. For first part please visit this link. In this article we will see some of the LDAP operations such as compare operation, search operation. We will also see how to change an LDAP password. The LDAP Compare Operation One of the simplest LDAP operations to perform is the compare operation. The LDAP compare operation takes a DN, an attribute name, and an attribute value and checks the directory to see if the given DN has an attribute with the given attribute name, and the given attribute value. If it returns true then there is a match, and if false then otherwise. The Python-LDAP API supports LDAP compare operations through the LDAPObject's compare() and compare_s() functions. The synchronous function is simple. It takes three string parameters (DN, attribute name, and asserted value), and returns 0 for false, and 1 for true: >>> dn = 'uid=matt,ou=users,dc=example,dc=com'>>> attr_name = 'sn'>>> attr_val = 'Butcher'>>> con.compare_s(dn, attr_name, attr_val)1 In this case, we check the DN uid=matt,ou=user,dc=example,dc=com to see if the surname (sn) has the value Butcher. It does, so the method returns 1. But let's set the attr_val to a different surname, one that the record does not contain: >>> attr_val = 'Smith'>>> con.compare_s(dn, attr_name, attr_val)0>>> Since the record identified by the DN uid=matt,ou=users,dc=example,dc=com does not have an SN attribute with the value Smith, this method returns 0, false. Historically, Python has treated the boolean value False with 0, and numeric values greater than zero as boolean True. So it is possible to use a compare like this: if con.compare_s(dn, attr_name, attr_val): print "Match"else: print "No match." If compare_s() returns 1, this will print Match. If it returns 0, it will print No match. Let's take a quick look, now, at the asynchronous version of the compare operation, compare(). As we saw in the section on binding, the asynchronous version starts the operation in a new thread, and then immediately returns control to the program, not waiting for the operation to complete. Later, the result of the operation can be examined using the LDAPObject's result() method. Running the compare() method is almost identical to the synchronized version, with the difference being the value returned: >>> retval = con.compare( dn, attr_name, attr_val )>>> print retval15 Here, we run a compare() method, storing the identification number for the returned information in the variable retval. Finding out the value of the returned information is a little trickier than one might guess. Any attempt to retrieve the result of a compare operation using the result() method will raise an exception. But, this is not a sign that the application has encountered an error. Instead, the exception itself indicates whether the compare operation returned true or false. For example, let's fetch the result for the previous operation in the way we might expect: >>> print con.result( retval )Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 405, in result res_type,res_data,res_msgid = self.result2(msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 409, in result2 res_type, res_data, res_msgid, srv_ctrls = self.result3 (msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 415, in result3 rtype, rdata, rmsgid, serverctrls = self._ldap_call (self._l.result3,msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 94, in _ldap_call result = func(*args,**kwargs)ldap.COMPARE_TRUE: {'info': '', 'desc': 'Compare True'} What is going on here? Attempting to retrieve the value resulted in an exception being thrown. As we can see from the last line, the exception raised was COMPARE_TRUE. Why? The developers of the Python-LDAP API worked around a difficulty in the standard LDAP C API by providing the results of the compare operation in the form of raised exceptions. Thus, the way to retrieve information from the asynchronous form of compare is with a try/except block: >>> retval = con.compare( dn, attr_name, attr_val )>>> try: ... con.result( retval )...... except ldap.COMPARE_TRUE:... print "Returned TRUE."...... except ldap.COMPARE_FALSE:... print "Returned FALSE."... Returned TRUE. In this example, we use the raised exception to determine whether the compare returned true, which raises the COMPARE_TRUE exception, or returned false, which raises COMPARE_FALSE. Performing compare operations is fairly straightforward, even with the nuances of the asynchronous version. The next operation we will examine is search. The Search Operation LDAP servers are intended as high read, low write databases, which means that it is expected that most operations that the server handles will be “read” operations that do not modify the contents of the directory information tree. And the main operation for reading a directory, as we have seen throughout this book, is the LDAP search operation. As a reminder, the LDAP search operation typically requires five parameters: The base DN, which indicates where in the directory information tree the search should start. The scope, which indicates how deeply the search should delve into the directory information tree. The search filter, which indicates which entries should be considered matches. The attribute list, which indicates which attributes of a matching record should be returned. A flag indicating whether attribute values should be returned (the Attrs Only flag). There are other additional parameters, such as time and size limits, and special client or server controls, but those are less frequently used. Once a search is processed, the server will return a bundle of information including the status of the search, all of the matching records (with the appropriate attributes), and, occasionally, error messages indicate some outstanding condition on the server. When writing Python-LDAP code to perform searches, we will need to handle all of these issues. In the Python-LDAP API, there are three (functional) variations of the search function: search() search_s() search_st() The first is the asynchronous form, and the second is the synchronous form. The third is a special form of the synchronous form that allows the programmer to add on a hard time limit in which the client must respond. There are two other versions of the search method, search_ext() and search_ext_s(). These two provide parameter placeholders for passing client and server extension mechanisms, but such extension handling is not yet functional, so neither of these functions is performatively different than the three above. We will begin by looking at the second method, search_s(). The search_s() function of the LDAPObject has two required parameters (Base DN and scope), and three optional parameters (search filter, attribute list, and the attrs only flag). Here, we will do a simple search for a list of surnames for all of the users in our directory information tree. For this, we will not need to set the attrs only flag (which is off by default, and, when turned on, will not return the attribute values). But we will need the other four parameters: Base DN: The users branch, ou=users,dc=example,dc=com Scope: Subtree (ldap.SCOPE_SUBTREE) Filter: Any person objects, (objectclass=person) Attributes: Surname (sn) Now we can perform our search in the Python interpreter: >>> import ldap>>> dn = "uid=matt,ou=users,dc=example,dc=com">>> pw = "secret">>> >>> con = ldap.initialize('ldap://localhost')>>> con.simple_bind_s( dn, pw )(97, [])>>>>>> base_dn = 'ou=users,dc=example,dc=com'>>> filter = '(objectclass=person)'>>> attrs = ['sn']>>> >>> con.search_s( base_dn, ldap.SCOPE_SUBTREE, filter, attrs )[('uid=matt,ou=Users,dc=example,dc=com', {'sn': ['Butcher']}),('uid=barbara,ou=Users,dc=example,dc=com', {'sn': ['Jensen']}),('uid=adam,ou=Users,dc=example,dc=com', {'sn': ['Smith']}),('uid=dave,ou=Users,dc=example,dc=com', {'sn': ['Hume']}),('uid=manny,ou=Users,dc=example,dc=com', {'sn': ['Kant']}),('uid=cicero,ou=Users,dc=example,dc=com', {'sn': ['Tullius']}),('uid=mary,ou=Users,dc=example,dc=com', {'sn': ['Wollstonecraft']}),('uid=thomas,ou=Users,dc=example,dc=com', {'sn': ['Hobbes']})]>>> The first seven lines should look familiar – there is nothing in these lines not covered in the previous sections. Next, we declare variables for the Base DN (base_dn), filter (filter), and attributes (attrs). While base_dn and filter are strings, attrs requires a list. In our case, it is a list with one member: ['sn']. Safe FiltersIf you are generating the LDAP filter dynamically (or letting users specify the filter), then you may want to use the escape_filter_chars() and filter_format() functions in the ldap.filter module to keep your filter strings safely escaped. We don't need to create a variable for the scope, since all of the available scopes (subtree, base, and onelevel) are available as constants in the ldap module: ldap.SCOPE_SUBTREE, ldap.SCOPE_BASE, and ldap.SCOPE_ONELEVEL. The line highlighted above shows the search, and the lines following – that big long messy conglomeration of tuples, dicts, and lists – is the result returned from the server. Strictly speaking, the result returned from search_s() is a list of tuples, where each tuple contains a DN string, and a dict of attributes. Each dict of attributes has a string key (the attribute name), and a list of string values. While this data structure is compact, it is not particularly easy to work with. For a complex data structure like this, it can be useful to create some wrapper objects to make use of this information a little more intuitive. The ldaphelper Helper Module To better work with LDAP results, we will create a simple package with just one class. This will be our ldaphelper module, stored in ldaphelper.py: import ldiffrom StringIO import StringIOfrom ldap.cidict import cidictdef get_search_results(results): """Given a set of results, return a list of LDAPSearchResult objects. """ res = [] if type(results) == tuple and len(results) == 2 : (code, arr) = results elif type(results) == list: arr = results if len(results) == 0: return res for item in arr: res.append( LDAPSearchResult(item) ) return resclass LDAPSearchResult: """A class to model LDAP results. """ dn = '' def __init__(self, entry_tuple): """Create a new LDAPSearchResult object.""" (dn, attrs) = entry_tuple if dn: self.dn = dn else: return self.attrs = cidict(attrs) def get_attributes(self): """Get a dictionary of all attributes. get_attributes()->{'name1':['value1','value2',...], 'name2: [value1...]} """ return self.attrs def set_attributes(self, attr_dict): """Set the list of attributes for this record. The format of the dictionary should be string key, list of string alues. e.g. {'cn': ['M Butcher','Matt Butcher']} set_attributes(attr_dictionary) """ self.attrs = cidict(attr_dict) def has_attribute(self, attr_name): """Returns true if there is an attribute by this name in the record. has_attribute(string attr_name)->boolean """ return self.attrs.has_key( attr_name ) def get_attr_values(self, key): """Get a list of attribute values. get_attr_values(string key)->['value1','value2'] """ return self.attrs[key] def get_attr_names(self): """Get a list of attribute names. get_attr_names()->['name1','name2',...] """ return self.attrs.keys() def get_dn(self): """Get the DN string for the record. get_dn()->string dn """ return self.dn def pretty_print(self): """Create a nice string representation of this object. pretty_print()->string """ str = "DN: " + self.dn + "n" for a, v_list in self.attrs.iteritems(): str = str + "Name: " + a + "n" for v in v_list: str = str + " Value: " + v + "n" str = str + "========" return str def to_ldif(self): """Get an LDIF representation of this record. to_ldif()->string """ out = StringIO() ldif_out = ldif.LDIFWriter(out) ldif_out.unparse(self.dn, self.attrs) return out.getvalue() This is a large chunk of code to take in at once, but the function of it is easy to describe. Remember, to use a Python module, you must make sure that the module is in the interpreter's path. See the official Python documentation (http://python.org) for more information. The package has two main components: the get_search_results() function, and the LDAPSearchResult class. The get_search_results() function simply takes the results from a search (either the synchronous ones, or the results from an asynchronous one, fetched with result()) and converts the results to a list of LDAPSearchResult objects. An LDAPSearchResults object provides some convenience methods for getting information about a record. The get_dn() method returns the record's DN, and the following methods all provide access to the attributes or the record: get_dn(): return the string DN for this record. get_attributes(): get a dictionary of all of the attributes. The keys  are attribute name strings, and the values are lists of attribute value  strings. set_attributes(): takes a dictionary with attribute names for keys, and  lists of attribute values for the value field. has_attribute(): takes a string attribute name and returns true if that attribute name is in the dict  of attributes returned. get_attr_values(): given an attribute name, this returns all of the  values for that attribute (or none if that attribute does not exist). get_attr_names(): returns a list of all of the attribute names for this  record. pretty_print(): returns a formatted string presentation of the record. to_ldif(): returns an LDIF formatted representation of the record. This object doesn't add much to the original returned data. It just makes it a little easier to access. Attribute NamesLDAP attributes can have multiple names. The attribute for surnames has two names: surname and sn (though most LDAP directory entries use sn). Either one might be returned by the server. To make your application aware of this difference, you can use the ldap.schema package to get schema information. The Case Sensitivity Gotcha There is one noteworthy detail in the code above. The search operation returns the attributes in a dictionary. The Python dictionary is case sensitive; the key TEST is different than the key test. This exemplifies a minor problem in dealing with LDAP information. Standards-compliant LDAP implementations treat some information in a case-insensitive way. The following items are, as a rule, treated as case-insensitive: Object class names: inetorgperson is treated as being the same as inetOrgPerson. Attribute Names: givenName is treated as being the same as givenname. Distinguished Names: DNs are case-insensitive, though the all-lower-case version of a DN is called  Normalized Form. The main area where this problem surfaces is in retrieving information from a search. Since the attributes are returned in a dict, they are, by default, treated as case-sensitive. For example, attrs.has_key('objectclass') will return False if the object class attribute name is spelled objectClass. To resolve this problem, the Python-LDAP developers created a case-insensitive dictionary implementation (ldap.cidict.cidict). This cidict class is used above to wrap the returned attribute dictionary. Make sure you do something similar in your own code, or you may end up with false misses when you look for attributes in a case-sensitive way, e.g. when you look for givenName in an entry where the attribute name is in the form givenname.
Read more
  • 0
  • 1
  • 18229
article-image-postgresqls-transaction-model
Packt
23 Oct 2009
7 min read
Save for later

PostgreSQL's Transaction Model

Packt
23 Oct 2009
7 min read
On Databases Databases come in many forms. The simplest definition of a database is any system of storing, organizing, and retrieving data. With this definition, things like memory, hard drives, file systems, files on those file systems (stored in plain text, tab-delimited, XML, JSON, or even BDB formats), and even applications like MySQL, PostgreSQL, and Oracle are considered databases. Databases allow users to: Store Data Organize Data Retrieve Data It is important to keep a broad perspective on what data and databases really are so that you can always choose the best solution for your particular problem. The SQL databases (MySQL, PostgreSQL, Oracle, and others) are remarkable because of the flexibility and performance they provide. In my work, I look to them first when developing an application, with an eye towards getting the data model right before optimization. Once the application is solid, and once I fully understand what parts of the data system are too slow or fast enough, then I can start building my own database on top of the file system or other existing technologies that will give me the kind of performance I need. PostgreSQL: Free, BSD -licensed popular database. http://postgresql.org/ MySQL: Free, GPL-licensed popular database. http://mysql.org Oracle: Commercial industrial database. http://oracle.com SQL Server: Microsoft's commercial database. http://www.microsoft.com/SQL/default.mspx Among the SQL databases, which one is best? There are many criteria I use to evaluate SQL databases, and the one I pay attention to most is how they comply (if at all) with the ACID model. And given the technical merits of the various SQL databases, I consistently choose PostgreSQL above all other SQL databases when given a choice. Allow me to explain why. The ACID Model ACID is an acronym, standing for the four words Atomicity, Consistency, Isolation, and Durability. These are fancy words for some very basic and essential concepts. Atomicity means that you either do all of the changes you want, or none of them, without leaving the database in some weird in-between state. When you take into account catastrophes like power failures or corruption, atomicity isn't as simple as it first seems. Consistency means that any state of the database will be internally consistent with the rules that constrain the data. That is, if you have a table with a primary key, then that table will not contain any violations of the primary key constraints after any transaction. Isolation means that you can be modifying many different parts of the database at the same time without affecting each other. (As a higher feature, there is Serialization, which requires that transactions occur one after the other, or at least the results of transactions.) Durability means that once a transaction completes, it is never lost, ever. Atomicity: All or nothing Consistency: Rules kept Isolation: No partials seen Durability: Doesn't disappear ACID compliance isn't rocket science, but it isn't trivial either. These requirements form a minimum standard absolutely necessary to provide a database for a reasonable application. That is, if you can't guarantee these things, then the users of your application are going to be frustrated since they assume, naturally, that the ACID model is followed. And if the users of the application get frustrated, then the developers of the application will get frustrated as they try to comply with the user's expectations. A lot of frustration can be avoided if the database simply complies with the principles of the ACID model. If the database gets it right, then the rest of the application will have no problem getting it right as well. Our users will be happy since their expectations of ACID compliance will be met. Remember: Users expect ACID! What Violating the ACID Model Looks Like To consider the importance of the ACID model, let's examine, briefly, what happens when the model is violated. When Atomicity isn't adhered to, users will see their data partially committed. For instance, they might find their online profile only partially modified, or their bank transfer partially transferred. This is, of course, devastating to the unwary user. When Consistency is violated, the rules that the data should follow aren't adhered to. Perhaps the number of friends shown doesn't match the friends they actually have in a social networking application. Or perhaps they see their bank balance doesn't match what the numbers add up to. Or worse, perhaps your order system is counting orders that don't even exist and not counting orders that do. When Isolation isn't guaranteed, they will either have to use a system where only one person can change something at a time, locking out all others, or they will see inconsistencies throughout the world of data, inconsistencies resulting from transactions that are in progress elsewhere. This will make the data unreliable just like violating Atomicity or Consistency. A bank user, for instance, will believe their transfer of funds was successful when in reality their money was simultaneously being withdrawn by another transaction. When Durability is lost, then users will never know if their transaction really went through, and won't mysteriously disappear down the road with all the trouble that entails. I am sure we have all had experiences dealing with data systems that didn't follow the ACID model. I remember the days when you had to save your files frequently, and even then you still weren't ensured that all of your data would be properly saved. I also recall applications that would make partial changes, or incomplete changes, and expose these inconsistent states to the user. In today's world, writing applications with faults like the above is simply inexcusable. There are too many tools out there that are readily available that make writing ACID compliant systems easy. One of those tools, probably the most popular of all, is the SQL database. Satisfying ACID with Transactions The principle way that databases comply with ACID requirements is through the concept of transactions. Ideally, each transaction would occur in an instant, updating the database according to the state of the database at that moment. In reality, this isn't possible. It takes time to accumulate the data and apply the changes. Typical transaction SQL commands: BEGIN: Start a new transaction COMMIT: Commit the transaction ROLLBACK: Roll back the transaction in progress Since multiple sessions can each be creating and applying a transaction simultaneously, special precautions have to be taken to ensure that the data that each transaction “sees” is consistent, and that the effects of each transaction appear all together or not at all. Special care is also taken to ensure that when a transaction is committed, the database will be put in a state where catastrophic events will not leave the transaction partially committed. Contrary to popular belief, there are a variety of ways that databases support transactions. It is well worth the time to read and understand PostgreSQL's two levels of transaction isolation and the four possible isolation levels in Section 12.2 of the PostgreSQL documentation. Note that some of the inferior levels of transaction isolation violate some extreme cases of ACID compliance for the sake of performance. These edge cases can be properly handled with appropriate use of row-locking techniques. Row-locking is an issue beyond this article. Keep in mind that the levels of transaction isolation are only what appear to users of the database. Inside the database, there is a remarkable variety of methods on actually implementing transactions. Consider that while you are in a transaction, making changes to the database, every other transaction has to see one version of the database while you see another. In effect, you have to have copies of some of the data lying around somewhere. Queries to that data have to know which version of the data to retrieve the copy, the original, or the modified version (and which modified version?) Changes to the data have to go somewhere the original, a copy, or some modified version (again, which?) Answering these questions leads to the various implementations of transactions in ACID compliant databases. For the purposes of this article, I will examine only two: Oracle's and PostgreSQL's implementations. If you are only familiar with Oracle, then hopefully you will learn something new and fascinating as you investigate PostgreSQL's method.
Read more
  • 0
  • 0
  • 7047

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-roles-and-permissions-moodle-administration-part1
Packt
23 Oct 2009
1 min read
Save for later

Roles and Permissions in Moodle Administration: Part1

Packt
23 Oct 2009
1 min read
Lets get started. Moodle's PreDefined Roles Moodle comes with a number of predefined roles. These standard roles are suitable for some educational setups, but most institutions require modifications to the roles' system in order to tailor Moodle to their specific needs. Each role has permissions for a number of actions that can be carried out in Moodle. For example, an administrator and a course creator are able to create new courses, whereas all other roles are denied this right. Likewise, a teacher is allowed to moderate forums, whereas students are only allowed to contribute to them. Before we can actually do anything with roles, we need to understand the concept of contexts, which is dealt with next. Contexts Contexts are the areas in Moodle where roles can be assigned to users. A role can be assigned within different contexts. A user has a role in any given context, where a context can be a course, an activity module, a user, a block, or Moodle itself. Moodle comes with the following seven contexts that you will come across a lot in this article.
Read more
  • 0
  • 0
  • 3470
article-image-front-page-customization-moodle
Packt
23 Oct 2009
11 min read
Save for later

Front Page Customization in Moodle

Packt
23 Oct 2009
11 min read
Look and Feel: An Overview Moodle can be fully customized in terms of layout and branding. It has to be stressed that certain aspects of changing the look and feel require some design skills. While you as an administrator will be able to make most of the relevant adjustments, it might be necessary to get a professional designer involved, especially when it comes to styling. The two relevant components for customization are the Moodle front page and Moodle themes, though this article will focus only on Moodle front page. Before going into further details, let's try to understand which part is responsible for which element of the look and feel of your site. Have a look at the screenshot that would follow. It shows the front page of Moodle site after you are logged in as an administrator. It is not obvious which parts are driven by the Moodle theme and by the front page settings. The next table sheds some light on this: Element Settings Theme Other Logos - x - Logged-in information (location and font) - x - Language Drop Down - - x Site Administration block (position) x - - Available Courses block (position) x - - Available Courses block (content) - - x Course categories and Calendar block (position) x - - Course categories and Calendar block (icons, fonts, colors) - x - Footer text - x - Footer logo - x - Copyright statement - x -   While this list is by no means complete, it hopefully gives you an idea that the look and feel of your Moodle site is driven by a number of different elemen In short, the settings (mostly front page settings as well as a few related parameters) dictate what content users will see before and after they log on. The theme is responsible for the design scheme or branding, that is, the header and footer as well as colors, fonts, icons, and so on used throughout the site. Now let's move towards the core part of this article. Customizing Your Front Page The appearance of Moodle's front page changes after a user has logged in. The content and layout of the page before and after login can be customized to represent the identity of your organization. Look at the following screenshot. It is the same site that the preceding screenshot was taken from, but before a user has logged in. In this particular example, a Login block is shown on the left and the Course categories are displayed in the center, as opposed to the list of available courses. Front Page Settings To customize the front page, you either have to be logged in as Moodle administrator, or have front-page-related permissions in the Front Page context. From the Site Administration block, select Front Page | Front Page Settings. The screen showing all available parameters will be loaded displaying your current settings that are changeable. ts. Setting Description Full site name This is the name that appears in the browser's title bar. It is usually the full name of your organization, or the name of the dedicated course, or qualification the site is used for. Short name for site This is the name that appears as the first item in the breadcrumb trail. Front Page Description This description of the site will be displayed on the front page via the Site Description block. It can, therefore, only be displayed in the left or right column, never in the center of the front page. The description text is also picked up by the Google search engine spider, if allowed. Front Page Moodle can display up to four elements in the center column of the front page when not logged in. List of courses List of categories News items Combo list(categories and courses) The order of the elements is the same as the one chosen in the pull-down menus. Front page items when logged in Same as "Front Page", but used when logged in. Include a topic section If ticked, an additional topic section (just like the topic blocks in the center column of a topics-format course) appears on top of the front page's center column. It can contain any mix of resources or activities available in Moodle. It is very often used to provide information about the site. News items to show Number of news items that are displayed. Courses per page This is a threshold setting that is used when displaying courses within categories. If there are more courses in a category than specified, page navigation will be displayed at the top of the page. Also, when a combo list is used, course names are only displayed if the number is less than the specified threshold. For all other categories, only the number of courses is shown after the category name. Allow visible courses within hidden categories By default, courses in hidden categories are not shown unless the said setting is applied. Default frontpage role If logged-in users should be allowed to participate in front page activities, a default front page role should be set. The default is None.   Arranging Front Page Blocks To configure the left and right column areas with blocks, you have to turn on editing (using the Blocks editing on button). The menu includes blocks that are not available in courses such as Course/Site description and Main menu. Blocks are added to the front page in exactly the same way as in courses. To change their position, use the standard arrows. The Main Menu block allows you to add any installed Moodle resource or activity inside the block. For example, using labels and links to (internal or external) websites, you are able to create a menu-like structure on your front page. If the Include a topic section parameter has been selected in the Front Page settings, you have to edit the part and add any installed Moodle activity or resource. This topic section is usually used by organizations to add a welcome message to visitors, often accompanied by a picture or other multimedia content. Login From a Different Website The purpose of the Login block is for users to authenticate themselves by entering their username and password. It is possible to log into Moodle from a different website, maybe your organization's homepage, effectively avoiding the Login block. To implement this, you will have to add some HTML code on that page as shown: <form class="loginform" name="login" method="post" action="http://www.mysite.com/login/index.php">   <p>Username :     <input size="10" name="username" />   </p>   <p>Password :     <input size="10" name="password" type="password" />   </p>   <p>     <input name="Submit" value="Login" type="submit" />   </p></form> The form will pass the username and password to your Moodle system. You will have to replace www.mysite.com with your URL. This address has to be entered in the Alternate Login URL field at Users | Authentication | Manage authentication in the Site Administration block. Other Front Page Items The Moodle front page is treated as a standalone component in Moodle, and therefore has a top-level menu with a number of features that can all be accessed via the Front Page item in the Site Administration menu. Having now looked in detail at the front page settings, let's turn to examining the other available options. Front Page Roles The front page has its own context in which roles can be assigned to users. This allows a separate user to develop and maintain the front page without having access to any other elements in Moodle. Since the front page is treated as a course, a Teacher role is usually sufficient for this. Front Page Backup and Restore The front page has its own backup and restore facilities to back up and restore all elements of the front page including any content. The mechanism of performing backup and restore is the same as for course backups.   Front page backups are stored in the backupdata folder in the Site Files area, and can be accessed by anybody who is aware of the URL. It is therefore best to move the created ZIP files to a more secure location. Front Page Questions Since the Moodle front page is treated in the same way as a course, it also has its own question bank, which is used to store any questions used on front-page quizzes. For more information on quizzes and the question bank, go to the MoodleDocs at http://docs.moodle.org/en/Quiz . Site Files The files areas of all courses are separate from each other, that is, files in Moodle belong to a course and can only be accessed by users who have been granted appropriate rights. The difference between Site files and the files area of any other course is that files in Site files can be accessed without logging in. Files placed in this location are meant for the front page, but can be accessed from anywhere in the system. In fact, if the location is known, files can be even be accessed from outside Moodle. Make sure that in the Site files area, you only place files that are acceptable to be seen by users who are not authenticated on your Moodle system. Typical files to be placed in this area are any images you want to show on the front page (such as the logo of your organization) or any document that you want to be accessed (for example, the curriculum). However, it is also used for other files that are required to be accessible without access to a course, such as the Site Policy Agreement, which has to be accepted before starting Moodle. To access these publicly available Site files elsewhere (for example, as a resource within other courses), you have to copy the link location that has the format: http://mysite.com/file.php/1/file.doc. Allow Personalization via My Moodle By default, the same front page is displayed for all users on your Moodle system. To relax this restriction and to allow users to personalize their own front page, you have to activate the My Moodle feature via the Force users to use My Moodle setting in Appearance | My Moodle in the Site Administration block. Once enabled, Moodle creates a /my directory for each user (except administrators) at their first login, which is displayed instead of the main Moodle front page. It is a very flexible feature that is similar to a customizable dashboard, but requires some more disk space on your server. Once logged in, users will have the ability to edit their page by adding blocks to their My Moodle area. The center of the page will be populated by the main front page, for instance displaying a list of courses, that users cannot modify. Making Blocks Sticky There might be some blocks that you wish to "stick", that is, display on each My Moodle page, making them effectively compulsory blocks. For example, you might want to pin the Calendar block on the top right corner of each user's My Moodle page. To do this, go to Modules | Blocks | Sticky blocks in the Site Administration block and select My Moodle from the pull-down menu. You can now add any item from the pull-down menu in the Blocks block. If the block is single instance (that is, only one occurrence is allowed per page), the block will not be available for the user to choose from. If the user has already selected a particular block, a duplicate will appear on their site, which can be edited and deleted. To prevent users from editing their My Moodle pages, change the moodle/my: manageblocks capability in the Authenticated user role from Allow to Not set. The sticky block feature is also available for course pages. A course creator has the ability to add and position blocks inside a course unless they have been made sticky. Select the Course page item from the same menu to configure the sticky blocks for courses, as shown in the preceding screenshot. Summary After providing a general overview of look and feel elements in Moodle, the article covered front page customization. As mentioned earlier, the front page in Moodle is a course. This has advantages (you can do everything you can do in a course and a little bit more), but it also has certain limitations (you can only do what you can do in a course and might feel limited by this). However, some organizations are now using the Moodle front page as their homepage.
Read more
  • 0
  • 0
  • 17368

article-image-interacting-databases-through-java-persistence-api
Packt
23 Oct 2009
17 min read
Save for later

Interacting with Databases through the Java Persistence API

Packt
23 Oct 2009
17 min read
We will look into: Creating our first JPA entity Interacting with JPA entities with entity manager Generating forms in JSF pages from JPA entities Generating JPA entities from an existing database schema JPA named queries and JPQL Entity relationships Generating complete JSF applications from JPA entities Creating Our First JPA Entity JPA entities are Java classes whose fields are persisted to a database by the JPA API. JPA entities are Plain Old Java Objects (POJOs), as such, they don't need to extend any specific parent class or implement any specific interface. A Java class is designated as a JPA entity by decorating it with the @Entity annotation. In order to create and test our first JPA entity, we will be creating a new web application using the JavaServer Faces framework. In this example we will name our application jpaweb. As with all of our examples, we will be using the bundled GlassFish application server. To create a new JPA Entity, we need to right-click on the project and select New | Entity Class. After doing so, NetBeans presents the New Entity Class wizard. At this point, we should specify the values for the Class Name and Package fields (Customer and com.ensode.jpaweb in our example), then click on the Create Persistence Unit... button. The Persistence Unit Name field is used to identify the persistence unit that will be generated by the wizard, it will be defined in a JPA configuration file named persistence.xml that NetBeans will automatically generate from the Create Persistence Unit wizard. The Create Persistence Unit wizard will suggest a name for our persistence unit, in most cases the default can be safely accepted. JPA is a specification for which several implementations exist. NetBeans supports several JPA implementations including Toplink, Hibernate, KODO, and OpenJPA. Since the bundled GlassFish application server includes Toplink as its default JPA implementation, it makes sense to take this default value for the Persistence Provider field when deploying our application to GlassFish. Before we can interact with a database from any Java EE 5 application, a database connection pool and data source need to be created in the application server. A database connection pool contains connection information that allow us to connect to our database, such as the server name, port, and credentials. The advantage of using a connection pool instead of directly opening a JDBC connection to a database is that database connections in a connection pool are never closed, they are simply allocated to applications as they need them. This results in performance improvements, since the operations of opening and closing database connections are expensive in terms of performance. Data sources allow us to obtain a connection from a connection pool by obtaining an instance of javax.sql.DataSource via JNDI, then invoking its getConnection() method to obtain a database connection from a connection pool. When dealing with JPA, we don't need to directly obtain a reference to a data source, it is all done automatically by the JPA API, but we still need to indicate the data source to use in the application's Persistence Unit. NetBeans comes with a few data sources and connection pools pre-configured. We could use one of these pre-configured resources for our application, however, NetBeans also allows creating these resources "on the fly", which is what we will be doing in our example. To create a new data source we need to select the New Data Source... item from the Data Source combo box. A data source needs to interact with a database connection pool. NetBeans comes pre-configured with a few connection pools out of the box, but just like with data sources, it allows us to create a new connection pool "on demand". In order to do this, we need to select the New Database Connection... item from the Database Connection combo box. NetBeans includes JDBC drivers for a few Relational Database Management Systems (RDBMS) such as JavaDB, MySQL, and PostgreSQL "out of the box". JavaDB is bundled with both GlassFish and NetBeans, therefore we picked JavaDB for our example. This way we avoid having to install an external RDBMS. For RDBMS systems that are not supported out of the box, we need to obtain a JDBC driver and let NetBeans know of it's location by selecting New Driver from the Name combo box. We then need to navigate to the location of a JAR file containing the JDBC driver. Consult your RDBMS documentation for details. JavaDB is installed in our workstation, therefore the server name to use is localhost. By default, JavaDB listens to port 1527, therefore that is the port we specify in the URL. We wish to connect to a database called jpaintro, therefore we specify it as the database name. Since the jpaintro database does not exist yet, we pass the attribute create=true to JavaDB, this attribute is used to create the database if it doesn't exist yet. Every JavaDB database contains a schema named APP, since each user by default uses a schema named after his/her own login name. The easiest way to get going is to create a user named "APP" and select a password for this user. Clicking on the Show JDBC URL checkbox reveals the JDBC URL for the connection we are setting up. The New Database Connection wizard warns us of potential security risks when choosing to let NetBeans remember the password for the database connection. Database passwords are scrambled (but not encrypted) and stored in an XML file under the .netbeans/[netbeans version]/config/Databases/Connections directory. If we follow common security practices such as locking our workstation when we walk away from it, the risks of having NetBeans remember database passwords will be minimal. Once we have created our new data source and connection pool, we can continue configuring our persistence unit. It is a good idea to leave the Use Java Transaction APIs checkbox checked. This will instruct our JPA implementation to use the Java Transaction API (JTA) to allow the application server to manage transactions. If we uncheck this box, we will need to manually write code to manage transactions. Most JPA implementations allow us to define a table generation strategy. We can instruct our JPA implementation to create tables for our entities when we deploy our application, to drop the tables then regenerate them when our application is deployed, or not create any tables at all. NetBeans allows us to specify the table generation strategy for our application by clicking the appropriate value in the Table Generation Strategy radio button group. When working with a new application, it is a good idea to select the Drop and Create table generation strategy. This will allow us to add, remove, and rename fields in our JPA entity at will without having to make the same changes in the database schema. When selecting this table generation strategy, tables in the database schema will be dropped and recreated, therefore any data previously persisted will be lost. Once we have created our new data source, database connection and persistence unit, we are ready to create our new JPA entity. We can do so by simply clicking on the Finish button. At this point NetBeans generates the source for our JPA entity. JPA allows the primary field of a JPA entity to map to any column type (VARCHAR, NUMBER). It is best practice to have a numeric surrogate primary key, that is, a primary key that serves only as an identifier and has no business meaning in the application. Selecting the default Primary Key type of long will allow for a wide range of values to be available for the primary keys of our entities. package com.ensode.jpaweb;import java.io.Serializable;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;@Entitypublic class Customer implements Serializable { private static final long serialVersionUID = 1L; private Long id; public void setId(Long id) { this.id = id; } @Id @GeneratedValue(strategy = GenerationType.AUTO) public Long getId() { return id; } //Other generated methods (hashCode(), equals() and //toString() omitted for brevity.} As we can see, a JPA entity is a standard Java object. There is no need to extend any special class or implement any special interface. What differentiates a JPA entity from other Java objects are a few JPA-specific annotations. The @Entity annotation is used to indicate that our class is a JPA entity. Any object we want to persist to a database via JPA must be annotated with this annotation. The @Id annotation is used to indicate what field in our JPA entity is its primary key. The primary key is a unique identifier for our entity. No two entities may have the same value for their primary key field. This annotation can be placed just above the getter method for the primary key class. This is the strategy that the NetBeans wizard follows. It is also correct to specify the annotation right above the field declaration. The @Entity and the @Id annotations are the bare minimum two annotations that a class needs in order to be considered a JPA entity. JPA allows primary keys to be automatically generated. In order to take advantage of this functionality, the @GeneratedValue annotation can be used. As we can see, the NetBeans generated JPA entity uses this annotation. This annotation is used to indicate the strategy to use to generate primary keys. All possible primary key generation strategies are listed in the following table:   Primary Key Generation Strategy   Description   GenerationType.AUTO   Indicates that the persistence provider will automatically select a primary key generation strategy. Used by default if no primary key generation strategy is specified.   GenerationType.IDENTITY   Indicates that an identity column in the database table the JPA entity maps to must be used to generate the primary key value.   GenerationType.SEQUENCE   Indicates that a database sequence should be used to generate the entity's primary key value.   GenerationType.TABLE   Indicates that a database table should be used to generate the entity's primary key value.       In most cases, the GenerationType.AUTO strategy works properly, therefore it is almost always used. For this reason the New Entity Class wizard uses this strategy. When using the sequence or table generation strategies, we might have to indicate the sequence or table used to generate the primary keys. These can be specified by using the @SequenceGenerator and @TableGenerator annotations, respectively. Consult the Java EE 5 JavaDoc at http://java.sun.com/javaee/5/docs/api/ for details. For further knowledge on primary key generation strategies you can refer EJB 3 Developer Guide by Michael Sikora, which is another book by Packt Publishing (http://www.packtpub.com/developer-guide-for-ejb3/book). Adding Persistent Fields to Our Entity At this point, our JPA entity contains a single field, its primary key. Admittedly not very useful, we need to add a few fields to be persisted to the database. package com.ensode.jpaweb;import java.io.Serializable;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;@Entitypublic class Customer implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String firstName; private String lastName; public void setId(Long id) { this.id = id; } @Id @GeneratedValue(strategy = GenerationType.AUTO) public Long getId() { return id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } //Additional methods omitted for brevity} In this modified version of our JPA entity, we added two fields to be persisted to the database; firstName will be used to store the user's first name, lastName will be used to store the user's last name. JPA entities need to follow standard JavaBean coding conventions. This means that they must have a public constructor that takes no arguments (one is automatically generated by the Java compiler if we don't specify any other constuctors), and all fields must be private, and accessed through getter and setter methods. Automatically Generating Getters and Setters In NetBeans, getter and setter methods can be generated automatically. Simply declare new fields as usual then use the "insert code" keyboard shortcut (default is Alt+Insert), then select Getter and Setter from the resulting pop-up window, then click on the check box next to the class name to select all fields, then click on the Generate button. Before we can use JPA persist our entity's fields into our database, we need to write some additional code. Creating a Data Access Object (DAO) It is a good idea to follow the DAO design pattern whenever we write code that interacts with a database. The DAO design pattern keeps all database access functionality in DAO classes. This has the benefit of creating a clear separation of concerns, leaving other layers in our application, such as the user interface logic and the business logic, free of any persistence logic. There is no special procedure in NetBeans to create a DAO. We simply follow the standard procedure to create a new class by selecting File | New, then selecting Java as the category and the Java Class as the file type, then entering a name and a package for the class. In our example, we will name our class CustomerDAO and place it in the com.ensode.jpaweb package. At this point, NetBeans create a very simple class containing only the package and class declarations. To take complete advantage of Java EE features such as dependency injection, we need to make our DAO a JSF managed bean. This can be accomplished by simply opening faces-config.xml, clicking its XML tab, then right-clicking on it and selecting JavaServer Faces | Add Managed Bean. We get the Add Manged Bean dialog as seen here: We need to enter a name, fully qualified name, and scope for our managed bean (which, in our case, is our DAO), then click on the Add button. This action results in our DAO being declared as a managed bean in our application's faces-config.xml configuration file. <managed-bean> <managed-bean-name>CustomerDAO</managed-bean-name> <managed-bean-class> com.ensode.jpaweb.CustomerDAO </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> We could at this point start writing our JPA code manually, but with NetBeans there is no need to do so, we can simply right-click on our code and select Persistence | Use Entity Manager, and most of the work is automatically done for us. Here is how our code looks like after doing this trivial procedure: package com.ensode.jpaweb;import javax.annotation.Resource;import javax.naming.Context;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;@PersistenceContext(name = "persistence/LogicalName", unitName = "jpawebPU")public class CustomerDAO { @Resource private javax.transaction.UserTransaction utx; protected void persist(Object object) { try { Context ctx = (Context) new javax.naming.InitialContext(). lookup("java:comp/env"); utx.begin(); EntityManager em = (EntityManager) ctx.lookup("persistence/LogicalName"); em.persist(object); utx.commit(); } catch (Exception e) { java.util.logging.Logger.getLogger( getClass().getName()).log( java.util.logging.Level.SEVERE, "exception caught", e); throw new RuntimeException(e); } }} All highlighted code is automatically generated by NetBeans. The main thing NetBeans does here is add a method that will automatically insert a new row in the database, effectively persisting our entity's properties. As we can see, NetBeans automatically generates all necessary import statements. Additionally, our new class is automatically decorated with the @PersistenceContext annotation. This annotation allows us to declare that our class depends on an EntityManager (we'll discuss EntityManager in more detail shortly). The value of its name attribute is a logical name we can use when doing a JNDI lookup for our EntityManager. NetBeans by default uses persistence/LogicalName as the value for this property. The Java Naming and Directory Interface (JNDI) is an API we can use to obtain resources, such as database connections and JMS queues, from a directory service. The value of the unitName attribute of the @PersistenceContext annotation refers to the name we gave our application's Persistence Unit. NetBeans also creates a new instance variable of type javax.transaction.UserTransaction. This variable is needed since all JPA code must be executed in a transaction. UserTransaction is part of the Java Transaction API (JTA). This API allows us to write code that is transactional in nature. Notice that the UserTransaction instance variable is decorated with the @Resource annotation. This annotation is used for dependency injection. in this case an instance of a class of type javax.transaction.UserTransaction will be instantiated automatically at run-time, without having to do a JNDI lookup or explicitly instantiating the class. Dependency injection is a new feature of Java EE 5 not present in previous versions of J2EE, but that was available and made popular in the Spring framework. With standard J2EE code, it was necessary to write boilerplate JNDI lookup code very frequently in order to obtain resources. To alleviate this situation, Java EE 5 made dependency injection part of the standard. The next thing we see is that NetBeans added a persist method that will persist a JPA entity, automatically inserting a new row containing our entity's fields into the database. As we can see, this method takes an instance of java.lang.Object as its single parameter. The reason for this is that the method can be used to persist any JPA entity (although in our example, we will use it to persist only instances of our Customer entity). The first thing the generated method does is obtain an instance of javax.naming.InitialContext by doing a JNDI lookup on java:comp/env. This JNDI name is the root context for all Java EE 5 components. The next thing the method does is initiate a transaction by invoking uxt.begin(). Notice that since the value of the utx instance variable was injected via dependency injection (by simply decorating its declaration with the @Resource annotation), there is no need to initialize this variable. Next, the method does a JNDI lookup to obtain an instance of javax.persistence.EntityManager. This class contains a number of methods to interact with the database. Notice that the JNDI name used to obtain an EntityManager matches the value of the name attribute of the @PersistenceContext annotation. Once an instance of EntityManager is obtained from the JNDI lookup, we persist our entity's properties by simply invoking the persist() method on it, passing the entity as a parameter to this method. At this point, the data in our JPA entity is inserted into the database. In order for our database insert to take effect, we must commit our transaction, which is done by invoking utx.commit(). It is always a good idea to look for exceptions when dealing with JPA code. The generated method does this, and if an exception is caught, it is logged and a RuntimeException is thrown. Throwing a RuntimeException has the effect of rolling back our transaction automatically, while letting the invoking code know that something went wrong in our method. The UserTransaction class has a rollback() method that we can use to roll back our transaction without having to throw a RunTimeException. At this point we have all the code we need to persist our entity's properties in the database. Now we need to write some additional code for the user interface part of our application. NetBeans can generate a rudimentary JSF page that will help us with this task.
Read more
  • 0
  • 0
  • 6087
Modal Close icon
Modal Close icon