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-maintaining-optimizing-and-upgrading-your-site-drupal-6-part-2
Packt
16 Oct 2009
9 min read
Save for later

Maintaining, Optimizing and Upgrading Your Site in Drupal 6: Part 2

Packt
16 Oct 2009
9 min read
Maintaining content As you continue to add content to your web site, you will need to ensure that your content is properly moderated, that old content is removed, and that changes to web site content are tracked. Creating content revisions Good Eatin' Goal: Create revisions of content to ensure that you have a complete record of changes to your web site's content. Additional modules needed: None. Basic steps We have simply updated our pages as necessary to add new functionality and content. However, if you have many editors, content that changes frequently, a need to view the history of a page, or need the ability to easily return to an old version of a page, you will want to store multiple revisions of your pages. To do this, carry out the following steps: Edit the content for which you want to create a new revision. Make the changes as needed and, before saving, expand the Revision information section. Select the Create new revision option and enter a message describing the changes that you have made to the node. When you save the content, you will see a new tab called Revisions. Clicking on this tab will show you a list of all of the revisions that have been created for the page. If you would like to return to an older version of the page, you can click the revert link. Or, if you want to remove an older revision, you can click the delete link to get rid of it permanently. You can control which users have access to the revision system by using the Permissions Manager. Drupal allows you to control which users can: view revisions, revert revisions, and delete revisions. If you want to force users to always create new revisions when editing content, edit the content type and then expand the Workflow settings. Change the default options to select the Create new revision option. When editors change content, the Create new revision option will be selected by default, and they will not be able to change the option unless they have the administer nodes permission. If you want to approve all revisions before publication, you can deselect the Published checkbox. Comparing content revisions Good Eatin' Goal: Compare the text of two different revisions of a page. Additional modules needed: Diff (http://drupal.org/project/diff). Basic steps Although the built-in functionality for creating revisions in Drupal works perfectly well, it can be difficult to review the changes that were made in each revision. The Diff module makes comparing revisions very easy. Begin by installing and activating the Diff module. To use the Diff module, simply view the revisions for any page. You will notice that the Revisions list has changed to allow you to select the revisions to be compared. Select the revisions to compare and then click on the Show diff button. Drupal will then display information about the text that has been changed, added, or deleted. Moderate content Good Eatin' Goal: Find questionable or offensive content, and remove it from your site, easily. Additional modules needed: Modr8 (http://drupal.org/project/modr8). Basic steps An unfortunate side effect of having a web site on the Internet is that, at some point, a malicious user will attempt to post inappropriate content on your site. If your site is extremely busy, you may find yourself with a large amount of content to review and approve. The Modr8 module can help you manage the workload and can send emails to users letting them know when their content has been approved or rejected. Begin by installing and activating the Modr8 module. The settings for the Modr8 module can be accessed by selecting Site configuration and then Modr8, from the Administer menu. The basic settings control how often logs are removed. Alternatively, you can choose to keep the logs forever. You can also change the number of items in the moderation queue to be displayed at a time, as well as the default action for the content that requires moderation. You can also configure the email settings for the moderation queue, including the text of the emails, and whether or not emails should be sent to the user who posted the content when their content is approved and/or when their content is rejected. You can also choose to send an email if the moderator does not take action for the item and wants to send a note to the author. If you would like new content to be added to the moderation queue automatically, you can edit the content type and select the In moderation queue setting in the workflow section. To view the moderation queue, select Content management and then Moderated content, from the Administer menu. The moderation queue appears as follows: From this page, you can approve, delete, or defer action on any content that needs moderation. After you make your changes, click Save to complete your selections. You can also display a log of all the moderation actions, by clicking on Reports and then Content moderation log. The moderation log appears as follows: Allowing users to report questionable or offensive content. Good Eatin' Goal: Get feedback from users to learn what they find offensive so the objectionable content can be removed. Additional modules needed: Abuse (http://drupal.org/project/abuse). Basic steps In the last task, we reviewed methods that allowed you to moderate every piece of content that is added to the site. However, this can be a time-intensive task if the proportion of content that you receive that is questionable is low. If this is the case, you can allow your users to help you to moderate the content by using the Abuse module, to let them report items that they find offensive. This strategy has a couple of advantages. Firstly, you are freed from the maintenance of pre-approving all content before it is published. Secondly, it ensures that the content meets community standards, rather than placing you or your editors in charge of defining community standards. The Abuse module also has a Watchlist component that allows you to flag content as suspicious or banned, and automatically move them into a queue for review by an administrator. Begin by downloading and installing the Abuse and Watchlist modules, both of which are included in the Abuse installation. We will begin by editing the Watchlist settings, which can be accessed by selecting Site configuration and then Watchlist settings, from the Administer menu. You can include any words that you want to, in the Watch list and Filtered/banned word list, depending on your target audience and your site's needs; just make sure that you enter one word per line. Items on the Watch list can be viewed while they are in the review queue, and items on the Filtered/banned word list will be hidden until they are reviewed. You can also control which items are automatically added to the Watch list or banned list, based on the Watchlist word settings configured above. You can also force moderation for specific types if they are more prone to abuse. We can now modify the Abuse Moderation settings by selecting Site configuration and then Abuse Moderation settings, from the Administer menu. The first setting controls what content types are subject to abuse reports. The next section of controls how abuse tickets are to be handled by your moderators. If you have multiple moderators for your site, you can select the Abuse Assigned Moderators option. If you use this, you will also need to store the maximum number of items that have been flagged for abuse that are added to the moderator's queue. If moderators live in different time zones, you can set an hour of the day at which all moderation queues are cleared, so that items do not remain in the moderation queue for an overly-long period of time. Finally, you can configure the settings related to all of the items that have been flagged as abusive by a user. The Abuse threshold controls how many complaints must be registered for an item before it is moved into the moderation queue. 3 is a good number to start with, but you may want to increase or decrease the threshold depending on the needs of your site. You can edit the reasons for flagging an item for abuse by selecting Site configuration, then Abuse Moderation settings, and finally Abuse Moderation reasons, from the Administer menu. All available reasons will be listed on the page using a format similar to the example above. You can add new reasons, remove reasons, or change the text for reasons from this page. Before the abuse module is activated, you need to assign permissions to users, so that they can flag content for review. Content that has the abuse module activated will have a new Flag as offensive link added to it, as shown in the following screenshot: When the user clicks on the Flag as offensive link, he or she will be presented with a form where he or she can specify their contact information, and a reason why he or she believes that the content is offensive. Administrators can review content that has been flagged as offensive by clicking on Content management and then Moderate. The administrators can click on the Get More Tickets link to have additional items assigned to them. Once a ticket has been assigned to them, the administrator can view information about the user who submitted the content as well as the user who flagged the content, and choose what action to take for the content. The administrator can either allow the content, or remove the content from the web site. The administrator can also optionally send a warning to the user without further action.
Read more
  • 0
  • 0
  • 1795

article-image-flex-101-flash-builder-4-part-1
Packt
16 Oct 2009
11 min read
Save for later

Flex 101 with Flash Builder 4: Part 1

Packt
16 Oct 2009
11 min read
  The article is intended towards developers who have never used Flex before and would like to exercise a “Hello World” kind of tutorial. The article does not aim to cover Flex and FB4 in detail but rather focuses on the mechanics of FB4 and getting an application running with minimal effort. For developers familiar with Flex and the predecessor to Flash Builder 4 (Flex Builder 2 or 3), it contains an introduction to FB4 and some differences in the way you go about building Flex Applications using FB4. Even if you have not programmed before and are looking at understanding how to make a start in developing applications, this would serve as a good start. The Flex Ecosystem The Flex ecosystem is a set of libraries, tools, languages and a deployment runtime that provides an end-to-end framework for designing, developing and deploying RIAs. All these together are being branded as a part of the Flash platform. In its latest release, Flex 4, special efforts have been put in to address the designer to developer workflow by letting graphic designers address layout, skinning, effects and general look and feel of your application and then the developers taking over to address the application logic, events, etc. To understand this at a high level, take a look at the diagram shown below. This is a very simplified diagram and the intention is to project a 10,000 ft view of the development, compilation and execution process. Let us understand the diagram now: The developer will typically work in the Flash Builder Application. Flash Builder is the Integrated Development Environment (IDE) that provides an environment for coding, compiling, running / debugging your Flex based applications. Your Flex Application will typically consist of MXML and ActionScript code. ActionScript is an ECMAScript compatible Object Oriented language, whereas MXML is an XML-based markup language. Using MXML you can define/layout your visual components like buttons, combobox, data grids, and others. Your application logic will be typically coded inside ActionScript classes/methods. While coding your Flex Application, you will make use of the Flex framework classes that provide most of the core functionality. Additional libraries like Flex Charting libraries and 3rd party components can be used in your application too. Flash Builder compiles all of this into object byte code that can be executed inside the Flash Player. Flash Player is the runtime host that executes your application. This is high level introduction to the ecosystem and as we work through the samples later on in the article, things will start falling into place. Flash Builder 4 Flash Builder is the new name for the development IDE previously known as Flex Builder. The latest release is 4 and it is currently in public beta. Flash Builder 4 is based on the Eclipse IDE, so if you are familiar with Eclipse based tools, you will be able to navigate your way quite easily. Flash Builder 4 like Flex Builder 3 previously is a commercial product and you need to purchase a development license. FB4 currently is in public beta and is available as a 30-day evaluation. Through the rest of the article, we will make use of FB4 and will be focused completely on that to build and run the sample applications. Let us now take a look at setting up FB4. Setting up your Development Environment To setup Flash Builder 4, follows these steps: The first step should be installing Flash Player 10 on your system. We will be developing with the Flex 4 SDK that comes along with Flash Builder 4 and it requires Flash Player 10. You can download the latest version of Flash Player from here: http://www.adobe.com/products/flashplayer/ Download Flash Builder 4 Public Beta from http://labs.adobe.com/technologies/flashbuilder4/. The page is shown below: After you download, run the installer program and proceed with the rest of the installation. Launch the Adobe Flash Builder Beta. It will prompt first with a message that it is a Trial version as shown below: To continue in evaluation mode, select the option highlighted above and click Next. This will launch the Flash Builder IDE. Let us start coding with Flash Builder 4 IDE. We will stick to tradition and write the “Hello World” application. Hello World using Flash Builder 4 In this section, we will be developing a basic Hello World application. While the application does not do much, it will help you get comfortable with the Flash Builder IDE. Launch the Flash Builder IDE. We will be creating a Flex Project. Flash Builder will help us create the Project that will contain all our files. To create a new Flex Project, click on the File → New → Flex Project as shown below: This will bring up a dialog in which you will need to specify more details about the Flex Project that you plan to develop. The dialog is shown below: You will need to provide at least the following information: Project Name: This is the name of your project. Enter a name that you want over here. In our case, we have named our project MyFirstFB4App. Application Type: We can develop both a Web version and a desktop version of our application using Flash Builder. The web application will then run inside of a web browser and execute within the Flash Player plug-in. We will go with the Web option over here. The Desktop application runs inside the Adobe Integrated Runtime environment and can have more desktop like features. We will skip that option for now. We will let the other options remain as is. We will use the Flex 4.0 SDK and currently we are not integrating with any Server side layer so we will leave that option as None/Other. Click on Finish at this point to create your Flex Project. This will create a main application file called MyFirstFB4App.mxml as shown below. We will come back to our coding a little later but first we must familiarize ourselves with the Flash Builder IDE. Let us first look at the Package Explorer to understand the files that have been created for the Flex Project. The screenshot is shown below: It consists of the main source file MyFirstFB4App.mxml. This is the main application file or in other words the bootstrap. All your source files (MXML and ActionScript code along with assets like images, and others should go under the src folder. They can optionally be placed in packages too. The Flex 4.0 framework consists of several libraries that you compile your code against. You would end up using its framework code, components (visual and non-visual) and other classes. These classes are packaged in a library file with an extension .swc. A list of library files is shown above. You do not need to typically do anything with it. Optionally, you can also use 3rd party components written by other companies and developers that are not part of the Flex framework. These libraries are packages as .SWC files too and they can be placed in the libs folder as shown in the previous screenshot. The typical step is to write and compile your code—build your project. If your build is successful, the object code is generated in the bin-debug folder. When you deploy your application to a Web Server, you will need to pickup the contents from this folder. We will come to that a little later. The html-template folder contains some boiler-plate code that contains the container HTML into which your object code will be referenced. It is possible to customize this but for now, we will not discuss that. Double-click MyFirstFB4App.mxml file. This is our main application file. The code listing is given below: <?xml version="1.0" encoding="utf-8"?> <s:Application minWidth="1024" minHeight="768"> </s:Application> As discussed before, you will typically write one or more MXML files that will contain typically your visual components (although there can be non-visual components also). By visual components, we mean controls like button, combobox, list, tree, and others. It could also contain layout components and containers that help you layout your design as per the application screen design. To view what components, you can place on the main application canvas, select the Design View as shown below: Have a look at the lower half of the left pane. You will see the Components tab as shown below, which would address most needs of your Application Visual design. Click on the Controls tree node as shown below. You will see several controls that you can use and from which, we will use the Button control for this application. Simply select the Button control and drag it to the Design View Canvas as shown below: This will drop an instance of the Button control on the Design View as shown below: Select the Button to see its properties panel as shown below. Properties Panel is where you can set several attributes at design time for the control. In case the Properties panel is not visible, you can get to that by selecting Window → Properties from the main menu. In the Properties panel, we can change several key attributes. All controls can be uniquely identified and addressed in your code via the ID attribute. This is a unique name that you need to provide. Go ahead and give it some meaningful name. In our case, we name it btnSayHello. Next we can change the label so that instead of Button, it can display a message for example, Say Hello. Finally we want to wire some code such that if the button is clicked, we can do some action like display a Message Box saying Hello World. To do that, click the icon next to the On click edit field as shown below. It will provide you two options. Select the option for Generate Event Handler. This will generate the code and switch to the Source view. The code is listed below for your reference. <?xml version="1.0" encoding="utf-8"?> <s:Application minWidth="1024" minHeight="768"> <fx:Script> <![CDATA[ protected function btnSayHello_clickHandler(event:MouseEvent):void { // TODO Auto-generated method stub } ]]> </fx:Script> <s:Button x="17" y="14" label="Button" id="btnSayHello" click="btnSayHello_clickHandler(event)"/> </s:Application> There are few things to note here. As mentioned most of your application logic will be written in ActionScript and that is exactly what Flash Builder has generated for you. All such code is typically added inside a scripting block marked with the <fx:Script> tag. You can place your ActionScript methods over here that can be used by the rest of the application. When we clicked on Generate Event Handler, Flash Builder generated the Event Handler code. This code is in ActionScript and was appropriately placed inside the <fx:Script> block for us. If you look at the code, you can see that it has added a function that is invoked when the click event is fired on the button. The method is btnSayHello_clickHandler and if you notice it has an empty method that is, no implementation. Let us run the application now to see what it looks like. To run the application, click on the   Run icon in the main toolbar of Flash Builder. This will launch the web application as shown below. Clicking the Say Hello button will not do anything at this point since there is no code written inside the handler as we saw above. To display the MessageBox, we add the code shown below (Only the Script section is shown below): <fx:Script> <![CDATA[ import mx.controls.Alert; protected function btnSayHello_clickHandler(event:MouseEvent):void { Alert.show("Hello World"); } ]]> </fx:Script> We use one of the classes (called Alert) from the Flex framework. Like any other language, we need to specify which package we are using the class from so that the compiler can understand it. The Alert class belongs to the mx.controls package and it has a static method called show() which takes a single parameter of type String. This String parameter is the message to be displayed and in our case it is "Hello World". To run this, click Ctrl-S to save your file or File →  Save from the main menu. And click on Run icon in the main toolbar. This will launch the application and on clicking the SayHello button, you will see the Hello World Alert window as shown below.
Read more
  • 0
  • 0
  • 3150

article-image-aspnet-35-cms-adding-security-and-membership-part-2
Packt
16 Oct 2009
8 min read
Save for later

ASP.NET 3.5 CMS: Adding Security and Membership (Part 2)

Packt
16 Oct 2009
8 min read
Now that you understand the process behind forms authentication, we need to add it to our application. The process will be slightly different because we already have a database to use, but without the ASP.NET membership schema. We'll add that to the database and then create some user accounts and membership roles to handle the security for our application. We'll also secure some of our content and add a menu to our Master Page to navigate between the pages of our Content Management System. Preparing an existing SQL database As we have an existing database, we can't create a new database for our membership and authentication system. Well, actually we could, but using a second database is problematic when we upload the application to a host because many web hosting companies allow only a single database under the hosting plan. Besides, we can easily add the membership schema the same way we did earlier in the article with our empty database, using aspnet_regsql.exe. Previously we used the wizard, this time we'll use the command line. If you take a look at the database in SQL Server Management Studio Express now, before we execute the command to add the schemas, you should see the few tables that were already created, as shown below: The aspnet_regsql.exe tool Using the command line, the executable is simple, as long as you know the command line arguments. The syntax and command arguments for aspnet_regsql.exe are available online at http://msdn.microsoft.com/en-us/library/x28wfk74.aspx. The following table shows the arguments we will use: Argument Description What we use -S The server name SQLEXPRESS -U The database username sa -P The database password SimpleCMS -d The database name SimpleCMS_Database -A The schema functions to install All functions   Our command line will look like this (all one line): aspnet_regsql.exe -S .SQLEXPRESS -U sa -P SimpleCMS -d SimpleCMS_Database -A all To run the command line, go to Start | Run and enter cmd in the Run dialog box. Press Enter and you will be at a command prompt. Type cd C:WINDOWSMicrosoft.NETFrameworkv2.0.50727 and press Enter again, and you will be in the correct folder to find aspnet_regsql.exe. Note that you may need to change the path if your ASP.NET framework files are in a different location. Type the command line above and press Enter, and you should see that the command completed successfully, with a dialog similar to that below: Now that we have executed the aspnet_regsql.exe command line, if you look at the database tables in SQL Server Management Studio Express, you should see the added table for the users, membership, and roles we will use in our application. User accounts Earlier in the article, we created a single user account for accessing protected content. In a real-world environment, we would normally have many user accounts, way too many to add each account to each page we wanted to protect. Fortunately, the ASP.NET framework provides us with membership roles that we can place user accounts in, allowing us to define our access by role, not by user account. But first, we need some user accounts. Let's start by creating three accounts in our application  - User1, User2, and Administrator. Open the SimpleCMS web site in Visual Web Developer 2008 Express. Use the downloadable code provided for Chapter 4 of this book, it has the web.config file modified similar to what we did when we walked through the forms authentication demo earlier in the chapter. Open the Web Site Administration Tool by clicking on Website and then ASP.NET Configuration. If you click on the Security tab, you will see that we have no users configured for this application.  As you did earlier in the article, click on Create User and create the three users with user names of User1, User2, and Administrator. Use Password! as the password for each, and provide a valid email address for each (they can have the same email for testing). Also, provide a question and answer such as Favorite Color? and Blue. You can use the same question and answer for all three accounts if you wish. Each user entry should look something like the following: If you return to the Security tab, you will notice that we have three user accounts, but no roles for those accounts. Let's add them next. Membership roles ASP.NET membership roles provide the ability to group many individual accounts into a single role to provide access to a resource such as a page or application. Changing access for an individual user then becomes a simple task of assigning them to or removing them from the appropriate role. A single user account can belong to multiple roles to provide extremely granular access to the application resources if your security demands are extensive. To add roles to our application, we first need to enable roles. On the Security tab of the Web Site Administration Tool, under Roles, you should see a link to enable roles. Enabling roles consists of simply adding the following line to the web.config file in the system.web section: <roleManager enabled="true" /> Similar to the membership provider we created earlier, roles require a role provider. We need to add this provider to the role manager, so edit the web.config roleManager section to read: <roleManager enabled="true"><providers><clear/><add name="AspNetSqlRoleProvider"connectionStringName="SimpleCMS_DatabaseConnectionString"applicationName="/"type="System.Web.Security.SqlRoleProvider, System.Web,Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /></providers></roleManager> This adds an AspNetSqlRoleProvider that uses our connection string to the SimpleCMS database. At this point we have no roles defined, so let's create a few. Open the Web Site Administration Tool. If it's already open, you may need to close and reopen it because we modified the web.config file to add the role provider. Now, open the Security tab. In the Roles section, click on Create or manage roles. Let's create an administration role first. We'll need it to secure areas to just administrative access. Simply enter Administrator, click on Add Role, and you'll see the new role in the list. Add roles for Author, Editor, and Registered User in the same manner. The roles list should look something like the following figure when you finish: Adding users to roles Once we have users and roles created, we need to assign users to roles. To do this, use the Security tab of the Web Site Administration Tool, under the Users section, to manage users.  You'll see a list of user accounts, in our case all three of them, along with the ability to edit the user, delete the user, and edit the user's roles. Click on Edit roles next to the Administrator user and you'll see a checkbox list of user roles this account can be added to. Any roles currently assigned to the user will be checked. As there are currently none, check the Administrator role, and the Administrator user will be immediately added to the Administrator role, as shown below: If you were to look at the database tables that hold the user accounts and roles, you would see something like this for the users: Similarly, the roles would look like this: You'll note that both the users and the roles contain an ApplicationID that defines what application these users and roles belong to, and that each user or role is identified by a UserID or RoleID. These are automatically created by the ASP.NET membership framework and are globally unique identifiers (GUIDs), which ensure that the specific user or role is unique across all possible applications and uses of this specific database store. You would also find in the database a table that identifies users in roles, looking something like this: You'll notice that this is a joining table, used in a database when there is a many-to-many relationship. Many users can belong to a role and a user can belong to many roles, thus the use of this table. You'll also notice that the database table uses the UserID and RoleID, making it very hard to simply look at this table directly to find what users are assigned to what roles.  Fortunately, with the ASP.NET framework, you're isolated from having to work directly with the database, as well as relieved from having to create it and the code needed to access it.
Read more
  • 0
  • 0
  • 2539

Packt
16 Oct 2009
17 min read
Save for later

WCF – Windows Communication Foundation

Packt
16 Oct 2009
17 min read
What is WCF? WCF is the acronym for Windows Communication Foundation. It is Microsoft's latest technology that enables applications in a distributed environment to communicate with each other. WCF is Microsoft's unified programming model for building service-oriented applications. It enables developers to build secure, reliable, transacted solutions that integrate across platforms and interoperate with existing investments. WCF is built on the Microsoft .NET Framework and simplifies the development of connected systems. It unifies a broad array of distributed systems capabilities in a composable, extensible architecture that supports multiple transports, messaging patterns, encodings, network topologies, and hosting models. It is the next version of several existing products—ASP.NET's web methods (ASMX) and Microsoft Web Services Enhancements (WSE) for Microsoft .NET, .NET Remoting, Enterprise Services, and System.Messaging. The purpose of WCF is to provide a single programming model that can be used to create services on the .NET platform for organizations. Why is WCF used for SOA? As we have seen in the previous section, WCF is an umbrella technology that covers ASMX web services, .NET remoting, WSE, Enterprise Service, and System.Messaging. It is designed to offer a manageable approach to distributed computing, broad interoperability, and direct support for service orientation. WCF supports many styles of distributed application development by providing a layered architecture. At its base, the WCF channel architecture provides asynchronous, untyped message-passing primitives. Built on top of this base are protocol facilities for secure, reliable, transacted data exchange and a broad choice of transport and encoding options. Let us take an example to see why WCF is a good approach for SOA. Suppose a company is designing a service to get loan information. This service could be used by the internal call center application, an Internet web application, and a third-party Java J2EE application such as a banking system. For interactions with the call center client application, performance is important. For communication with the J2EE-based application however, interoperability becomes the highest goal. The security requirements are also quite different between the local Windows-based application, and the J2EE-based application running on another operating system. Even transactional requirements might vary, with only the internal application being allowed to make transactional requests. With these complex requirements, it is not easy to build the desired service with any single existing technology. For example, the ASMX technology may serve well for the interoperability, but its performance may not be ideal. The .NET remoting will be a good choice from the performance perspective, but it is not good at interoperability. Enterprise Services could be used for managing object lifetimes and defining distributed transactions, but Enterprise Services supports only a limited set of communication options. Now with WCF, it is much easier to implement this service. As WCF has unified a broad array of distributed systems capabilities, the get loan service can be built with WCF for all of its application-to-application communication. The following shows how WCF addresses each of these requirements: Because WCF can communicate using web service standards, interoperability with other platforms that also support SOAP, such as the leading J2EE-based application servers, is straightforward. You can also configure and extend WCF to communicate with web services using messages not based on SOAP, for example, simple XML formats such as RSS. Performance is of paramount concern for most businesses. WCF was developed with the goal of being one of the fastest distributed application platforms developed by Microsoft. To allow for optimal performance when both parties in a communication are built on WCF, the wire encoding used in this case is an optimized binary version of an XML Information Set. Using this option makes sense for communication with the call center client application, because it is also built on WCF, and performance is an important concern. Managing object lifetimes, defining distributed transactions, and other aspects of Enterprise Services, are now provided by WCF. They are available to any WCF-based application, which means that the get loan service can use them with any of the other applications that it communicates with. Because it supports a large set of the WS-* specifications, WCF helps to provide reliability, security, and transactions when communicating with any platform that supports these specifications. The WCF option for queued messaging, built on Message Queuing, allows applications to use persistent queuing without using another set of application programming interfaces. The result of this unification is greater functionality, and significantly reduced complexity. WCF architecture The following diagram illustrates the major layers of the Windows Communication Foundation (WCF) architecture. This diagram is taken from the Microsoft web site (http://msdn.microsoft.com/en-us/library/ms733128.aspx): The Contracts layer defines various aspects of the message system. For example, the Data Contract describes every parameter that makes up every message that a service can create or consume. The Service runtime layer contains the behaviors that occur only during the actual operation of the service, that is, the runtime behaviors of the service. The Messaging layer is composed of channels. A channel is a component that processes a message in some way, for example, authenticating a message. In its final form, a service is a program. Like other programs, a service must be run in an executable format. This is known as the hosting application. In the next section, we will explain these concepts in detail. Basic WCF concepts—WCF ABCs There are many terms and concepts around WCF, such as address, binding, contract, endpoint, behavior, hosting, and channels. Understanding these terms is very helpful when using WCF. Address The WCF Address is a specific location for a service. It is the specific place to which a message will be sent. All WCF services are deployed at a specific address, listening at that address for incoming requests. A WCF Address is normally specified as a URI, with the first part specifying the transport mechanism, and the hierarchical part specifying the unique location of the service. For example, http://www.myweb.com/myWCFServices/SampleService can be an address for a WCF service. This WCF service uses HTTP as its transport protocol, and it is located on the server www.myweb.com, with a unique service path of myWCFServices/SampleService. The following diagram illustrates the three parts of a WCF service address. Binding Bindings are used to specify the transport, encoding, and protocol details required for clients and services to communicate with each other. Bindings are what WCF uses to generate the underlying wire representation of the endpoint. So, most of the details of the binding must be agreed upon by the parties that are communicating. The easiest way to achieve this is for clients of a service to use the same binding that the service uses. A binding is made up of a collection of binding elements. Each element describes some aspect of how the service communicates with clients. A binding must include at least one transport binding element, at least one message encoding binding element (which can be provided by the transport binding element by default), and any number of other protocol binding elements. The process that builds a runtime out of this description allows each binding element to contribute code to that runtime. WCF provides bindings that contain common selections of binding elements. These can either be used with their default settings, or the default values can be modified according to user requirements. These system-provided bindings have properties that allow direct control over the binding elements and their settings. The following are some examples of the system-provided bindings: BasicHttpBinding, WSHttpBinding, WSDualHttpBinding, WSFederationHttpBinding, NetTcpBinding, NetNamedPipeBinding, NetMsmqBinding, NetPeerTcpBinding, and MsmqIntegrationBinding. Each one of these built-in bindings has predefined required elements for a common task, and is ready to be used in your project. For instance, the BasicHttpBinding uses HTTP as the transport for sending SOAP 1.1 messages, and it has attributes and elements such as receiveTimeout, sendTimeout, maxMessageSize, and maxBufferSize. You can accept the default settings of its attributes and elements, or overwrite them as needed. Contract A WCF contract is a set of specifications that define the interfaces of a WCF service. A WCF service communicates with other applications according to its contracts. There are several types of WCF contracts, such as Service Contract, Operation Contract, Data Contract, Message Contract, and Fault Contract. Service contract A service contract is the interface of the WCF service. Basically, it tells others what the service can do. It may include service-level settings, such as the name of the service, the namespace of the service, and the corresponding callback contracts of the service. Inside the interface, it can define a bunch of methods, or service operations for specific tasks. Normally, a WCF service has at least one service contract. Operation contract An operation contract is defined within a service contract. It defines the parameters and return type of an operation. An operation can take data of a primitive (native) data type, such as an integer as a parameter, or it can take a message, which should be defined as a message contract type. Just as a service contract is an interface, an operation contract is a definition of an operation. It has to be implemented in order that the service functions as a WCF service. An operation contract also defines operation-level settings, such as the transaction flow of the operation, the directions of the operation (one-way, two-way, or both ways), and fault contract of the operation. The following is an example of an operation contract: [WCF::FaultContract(typeof(MyWCF.EasyNorthwind.FaultContracts.ProductFault))]MyWCF.EasyNorthwind.MessageContracts.GetProductResponseGetProduct(MyWCF.EasyNorthwind.MessageContracts.GetProductRequest request); In this example, the operation contract's name is GetProduct, and it takes one input parameter, which is of type GetProductRequest (a message contract) and has one return value, which is of type GetProductResponse (another message contract). It may return a fault message, which is of type ProductFault (a fault contract), to the client applications. We will cover message contract and fault contract in the following sections. Message contract If an operation contract needs to pass a message as a parameter or return a message, the type of these messages will be defined as message contracts. A message contract defines the elements of the message, as well as any message-related settings, such as the level of message security, and also whether an element should go to the header or to the body. The following is a message contract example: namespace MyWCF.EasyNorthwind.MessageContracts{ /// <summary> /// Service Contract Class - GetProductResponse /// </summary> [WCF::MessageContract(IsWrapped = false)] public partial class GetProductResponse { private MyWCF.EasyNorthwind.DataContracts.Product product; [WCF::MessageBodyMember(Name = "Product")] public MyWCF.EasyNorthwind.DataContracts.Product Product { get { return product; } set { product = value; } } }} In this example, the namespace of the message contract is MyWCF.EasyNorthwind.MessageContracts, and the message contract's name is GetProductResponse. This message contract has one member, which is of type Product. Data contract Data contracts are data types of the WCF service. All data types used by the WCF service must be described in metadata to enable other applications to interoperate with the service. A data contract can be used by an operation contract as a parameter or return type, or it can be used by a message contract to define elements. If a WCF service uses only primitive (native) data types, it is not necessary to define any data contract. The following is an of example data contract: namespace MyWCF.EasyNorthwind.DataContracts{ /// <summary> /// Data Contract Class - Product /// </summary> [WcfSerialization::DataContract(Namespace = "http://MyCompany.com/ ProductService/EasyWCF/2008/05", Name = "Product")] public partial class Product { private int productID; private string productName; [WcfSerialization::DataMember(Name = "ProductID", IsRequired = false, Order = 0)] public int ProductID { get { return productID; } set { productID = value; } } [WcfSerialization::DataMember(Name = "ProductName", IsRequired = false, Order = 1)] public string ProductName { get { return productName; } set { productName = value; } } }} In this example, the namespace of the data contract is MyWCF.EasyNorthwind.DataContracts, the name of the data contract is Product, and this data contract has two members (ProductID and ProductName).   Fault contract In any WCF service operation contract, if an error can be returned to the caller, the caller should be warned of that error. These error types are defined as fault contracts. An operation can have zero or more fault contracts associated with it. The following is a fault contract example: namespace MyWCF.EasyNorthwind.FaultContracts{ /// <summary> /// Data Contract Class - ProductFault /// </summary> [WcfSerialization::DataContract(Namespace = "http://MyCompany.com/ ProductService/EasyWCF/2008/05", Name = "ProductFault")] public partial class ProductFault { private string faultMessage; [WcfSerialization::DataMember(Name = "FaultMessage", IsRequired = false, Order = 0)] public string FaultMessage { get { return faultMessage; } set { faultMessage = value; } } }} In this example, the namespace of the fault contract is MyWCF.EasyNorthwind.FaultContracts, the name of the fault contract is ProductFault, and the fault contract has only one member (FaultMessage). Endpoint Messages are sent between endpoints. Endpoints are places where messages are sent or received (or both), and they define all of the information required for the message exchange. A service exposes one or more application endpoints (as well as zero or more infrastructure endpoints). A service can expose this information as the metadata that clients can process to generate appropriate WCF clients and communication stacks. When needed, the client generates an endpoint that is compatible with one of the service's endpoints. A WCF service endpoint has an address, a binding, and a service contract(WCF ABC). The endpoint's address is a network address where the endpoint resides. It describes, in a standard-based way, where messages should be sent. Each endpoint normally has one unique address, but sometimes two or more endpoints can share the same address. The endpoint's binding specifies how the endpoint communicates with the world, including things such as transport protocol (TCP, HTTP), encoding (text, binary), and security requirements (SSL, SOAP message security). The endpoint's contract specifies what the endpoint communicates, and is essentially a collection of messages organized in the operations that have basic Message Exchange Patterns (MEPs) such as one-way, duplex, or request/reply. The following diagram shows the components of a WCF service endpoint. Behavior A WCF behavior is a type, or settings to extend the functionality of the original type. There are many types of behaviors in WCF, such as service behavior, binding behavior, contract behavior, security behavior and channel behavior. For example, a new service behavior can be defined to specify the transaction timeout of the service, the maximum concurrent instances of the service, and whether the service publishes metadata. Behaviors are configured in the WCF service configuration file. Hosting A WCF service is a component that can be called by other applications. It must be hosted in an environment in order to be discovered and used by others. The WCF host is an application that controls the lifetime of the service. With .NET 3.0 and beyond, there are several ways to host the service. Self hosting A WCF service can be self-hosted, which means that the service runs as a standalone application and controls its own lifetime. This is the most flexible and easiest way of hosting a WCF service, but its availability and features are limited. Windows services hosting A WCF service can also be hosted as a Windows service. A Windows service is a process managed by the operating system and it is automatically started when Windows is started (if it is configured to do so). However, it lacks some critical features (such as versioning) for WCF services. IIS hosting A better way of hosting a WCF service is to use IIS. This is the traditional way of hosting a web service. IIS, by nature, has many useful features, such as process recycling, idle shutdown, process health monitoring, message-based activation, high availability, easy manageability, versioning, and deployment scenarios. All of these features are required for enterprise-level WCF services. Windows Activation Services hosting The IIS hosting method, however, comes with several limitations in the service-orientation world; the dependency on HTTP is the main culprit. With IIS hosting, many of WCF's flexible options can't be utilized. This is the reason why Microsoft specifically developed a new method, called Windows Activation Services, to host WCF services. Windows Process Activation Service (WAS) is the new process activation mechanism for Windows Server 2008 that is also available on Windows Vista. It retains the familiar IIS 6.0 process model (application pools and message-based process activation) and hosting features (such as rapid failure protection, health monitoring, and recycling), but it removes the dependency on HTTP from the activation architecture. IIS 7.0 uses WAS to accomplish message-based activation over HTTP. Additional WCF components also plug into WAS to provide message-based activation over the other protocols that WCF supports, such as TCP, MSMQ, and named pipes. This allows applications that use the non-HTTP communication protocols to use the IIS features such as process recycling, rapid fail protection, and the common configuration systems that were only available to HTTP-based applications. This hosting option requires that WAS be properly configured, but it does not require you to write any hosting code as part of the application. [Microsoft MSN, Hosting Services, retrieved on 3/6/2008 from http://msdn2.microsoft.com/en-us/library/ms730158.aspx] Channels As we have seen in the previous sections, a WCF service has to be hosted in an application on the server side. On the client side, the client applications have to specify the bindings to connect to the WCF services. The binding elements are interfaces, and they have to be implemented in concrete classes. The concrete implementation of a binding element is called a channel. The binding represents the configuration, and the channel is the implementation associated with that configuration. Therefore, there is a channel associated with each binding element. Channels stack on top of one another to create the concrete implementation of the binding—the channel stack. The WCF channel stack is a layered communication stack with one or more channels that process messages. At the bottom of the stack is a transport channel that is responsible for adapting the channel stack to the underlying transport (for example, TCP, HTTP, SMTP and other types of transport). Channels provide a low-level programming model for sending and receiving messages. This programming model relies on several interfaces and other types collectively known as the WCF channel model. The following diagram shows a simple channel stack: Metadata The metadata of a service describes the characteristics of the service that an external entity needs to understand in order to communicate with the service. Metadata can be consumed by the ServiceModel Metadata Utility Tool (Svcutil.exe) to generate a WCF client and the accompanying configuration that a client application can use to interact with the service. The metadata exposed by the service includes XML schema documents, which define the data contract of the service, and WSDL documents, which describe the methods of the service. Though WCF services will always have metadata, it is possible to hide the metadata from outsiders. If you do so, you have to pass the metadata to the client side by other means. This practice is not common, but it gives your services an extra layer of security. When enabled via the configuration settings through metadata behavior, metadata for the service can be retrieved by inspecting the service and its endpoints. The following configuration setting in a WCF service configuration file will enable the metadata publishing for HTTP transport protocol: <serviceMetadata httpGetEnabled="true" />
Read more
  • 0
  • 0
  • 2350

article-image-human-readable-rules-drools-jboss-rules-50part-2
Packt
16 Oct 2009
5 min read
Save for later

Human-readable Rules with Drools JBoss Rules 5.0(Part 2)

Packt
16 Oct 2009
5 min read
Drools Agenda Before we talk about how to manage rule execution order, we have to understand Drools Agenda. When an object is inserted into the knowledge session, Drools tries to match this object with all of the possible rules. If a rule has all of its conditions met, its consequence can be executed. We say that a rule is activated. Drools records this event by placing this rule onto its agenda (it is a collection of activated rules). As you may imagine, many rules can be activated, and also deactivated, depending on what objects are in the rule session. After the fireAllRules method call, Drools picks one rule from the agenda and executes its consequence. It may or may not cause further activations or deactivations. This continues until the Drools Agenda is empty. The purpose of the agenda is to manage the execution order of rules. Methods for managing rule execution order The following are the methods for managing the rule execution order (from the user's perspective). They can be viewed as alternatives to ruleflow. All of them are defined as rule attributes. salience: This is the most basic one. Every rule has a salience value. By default it is set to 0. Rules with higher salience value will fire first. The problem with this approach is that it is hard to maintain. If we want to add new rule with some priority, we may have to shift the priorities of existing rules. It is often hard to figure out why a rule has certain salience, so we have to comment every salience value. It creates an invisible dependency on other rules. activation-group: This used to be called xor-group. When two or more rules with the same activation group are on the agenda, Drools will fire just one of them. agenda-group: Every rule has an agenda group. By default it is MAIN. However, it can be overridden. This allows us to partition Drools Agenda into multiple groups that can be executed separately. The figure above shows partitioned Agenda with activated rules. The matched rules are coming from left and going into Agenda. One rule is chosen from the Agenda at a time and then executed/fired. At runtime, we can programmatically set the active Agenda group (through the getAgenda().getAgendaGroup(String agendaGroup).setFocus() method of KnowledgeRuntime), or declaratively, by setting the rule attribute auto-focus to true. When a rule is activated and has this attribute set to true, the active agenda group is automatically changed to rule's agenda group. Drools maintains a stack of agenda groups. Whenever the focus is set to a different agenda group, Drools adds this group onto this stack. When there are no rules to fire in the current agenda group, Drools pops from the stack and sets the agenda group to the next one. Agenda groups are similar to ruleflow groups with the exception that ruleflow groups are not stacked. Note that only one instance of each of these attributes is allowed per rule (for example, a rule can only be in one ruleflow-group ; however, it can also define salience within that group). Ruleflow As we've already said, ruleflow can externalize the execution order from the rule definitions. Rules just define a ruleflow-group attribute, which is similar to agenda-group. It is then used to define the execution order. A simple ruleflow (in the example.rf file) is shown in the following screenshot: The preceding screenshot shows a ruleflow opened with the Drools Eclipse plugin. On the lefthand side are the components that can be used when building a ruleflow. On the righthand side is the ruleflow itself. It has a Start node which goes to ruleflow group called Group 1. After it finishes execution, an Action is executed, then the flow continues to another ruleflow group called Group 2, and finally it finishes at an End node. Ruleflow definitions are stored in a file with the .rf extension. This file has an XML format and defines the structure and layout for presentational purposes. Another useful rule attribute for managing which rules can be activated is lock-on-active. It is a special form of the no-loop attribute. It can be used in combination with ruleflow-group or agenda-group. If it is set to true, and an agenda/ruleflow group becomes active/focused, it discards any further activations for the rule until a different group becomes active. Please note that activations that are already on the agenda will be fired. A ruleflow consists of various nodes. Each node has a name, type, and other specific attributes. You can see and change these attributes by opening the standard Properties view in Eclipse while editing the ruleflow file. The basic node types are as follows: Start End Action RuleFlowGroup Split Join They are discussed in the following sections. Start It is the initial node. The flow begins here. Each ruleflow needs one start node. This node has no incoming connection—just one outgoing connection. End It is a terminal node. When execution reaches this node, the whole ruleflow is terminated (all of the active nodes are canceled). This node has one incoming connection and no outgoing connections. Action Used to execute some arbitrary block of code. It is similar to the rule consequence—it can reference global variables and can specify dialect. RuleFlowGroup This node will activate a ruleflow-group, as specified by its RuleFlowGroup attribute. It should match the value in ruleflow-group rule attribute.  
Read more
  • 0
  • 0
  • 5015

article-image-jboss-portals-and-ajax-part-2
Packt
16 Oct 2009
7 min read
Save for later

JBoss Portals and AJAX - Part 2

Packt
16 Oct 2009
7 min read
AJAX support for markup Special tags are added to layout JSPs that facilitate the placement of AJAX features on a page. Similarly, renderers are used to interpret the tags and to render AJAX-driven content. The obvious advantage is the in-built support for the auto-creation and control of AJAX components on portal pages. Layout markup Layouts provide a structure for the creation and serving of portal pages. Layouts aggregate all of the content generated by the portlet, based on region and order, merge them with some additional content provided by the portal, and serve a response back to the user. By providing support for AJAX in the layout, helps facilitate the easy development and implementation of dynamic functionality in pages, with minimal effort. Layout markup is implemented using JSP tags. The JBoss JSP tag library, portlet-layout.tld, offers tags that facilitate the implementation of AJAX features in layouts. A JSP layout can be changed to an AJAX-supported page simply by adding references to the tags. Hence, using tags also helps with the easy implementation of features. The following is the layout page from the default portal generic layout ${JBOSS_PORTAL_HOME}serverdefaultdeployjboss-portal.sarportal-core.warlayoutsgenericindex.jsp, and shows AJAX support implemented as tags: <%@ page import="org.jboss.portal.server.PortalConstants" %><%@ taglib uri="/WEB-INF/theme/portal-layout.tld" prefix="p" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html ><head> <title><%= PortalConstants.VERSION.toString() %></title> <meta http-equiv="Content-Type" content="text/html;"/> <!-- to correct the unsightly Flash of Unstyled Content. --> <script type="text/javascript"></script> <!-- inject the theme, default to the Renaissance theme if nothing is selected for the portal or the page --> <p:theme themeName="renaissance"/> <!-- insert header content that was possibly set by portlets on the page --> <p:headerContent/> <%@include file="/layouts/common/modal_head.jsp"%></head><body id="body"><p:region regionName='AJAXScripts' regionID='AJAXScripts'/><%@include file="/layouts/common/modal_body.jsp"%><div id="portal-container"> <div id="sizer"> <div id="expander"> <div id="logoName"></div> <table border="0" cellpadding="0" cellspacing="0" id="header-container"> <tr> <td align="center" valign="top" id="header"> <!-- Utility controls --> <p:region regionName='dashboardnav' regionID='dashboardnav'/> <!-- navigation tabs and such --> <p:region regionName='navigation' regionID='navigation'/> <div id="spacer"></div> </td> </tr> </table> <div id="content-container"> <!-- insert the content of the 'left' region of the page, and assign the css selector id 'regionA' --> <p:region regionName='left' regionID='regionA'/> <!-- insert the content of the 'center' region of the page, and assign the css selector id 'regionB' --> <p:region regionName='center' regionID='regionB'/> <hr class="cleaner"/> </div> </div> </div></div><div id="footer-container" class="portal-copyright">Powered by <a class="portal-copyright" href="http://www.jboss.com/products/jbossportal">JBoss Portal</a><br/></div><p:region regionName='AJAXFooter' regionID='AJAXFooter'/></body></html> Renderer markup The portal combines the renderers and layouts to generate the final content. Enabling support for AJAX in the renderer just requires adding the statement <ajax-enabled>true</ajax-enabled> to the renderer descriptor. The following example, at {JBOSS_PORTAL_HOME}serverdefaultdeployjbossportal.sarportal-core.warWEB-INFlayoutportal-renderSet.xml, shows the renderer configuration of the emptyRenderer RenderSet for AJAX support: <renderSet name="emptyRenderer"> <set content-type="text/html"> <ajax-enabled>true</ajax-enabled> <region-renderer> org.jboss.portal.theme.impl.render.empty.EmptyRegionRenderer </region-renderer> <window-renderer> org.jboss.portal.theme.impl.render.empty.EmptyWindowRenderer </window-renderer> <portlet-renderer> org.jboss.portal.theme.impl.render.empty.EmptyPortletRenderer </portlet-renderer> <decoration-renderer> org.jboss.portal.theme.impl.render.empty.EmptyDecorationRenderer </decoration-renderer> </set></renderSet> AJAX support for content Whereas the layout and renderer contribute to AJAX behavior at the markup level, JBoss portal's support for object-level configuration can be leveraged to provide AJAX support at the page level. The object property inherits a configured behavior from its parent. Currently, two features are offered for AJAX-driven content: Drag and drop: Facilitates easy movement of portlets to various locations on screen using the mouse. Screen Refresh: Allows sub-components of pages or individual portlets to refresh themselves without refreshing the entire page. Drag-and-Drop As the name suggests, this feature is triggered by a user action, and allows a portlet to detach itself from a specific location on the page and move to a different location on the page. This allows for the customization of the user interface to a form that is most convenient to the user. The dynamic view behavior comes from a combination of DHTML and asynchronous server-side communication. Due to the nature of the behavior, drag-and-drop capability is available and effective only in dashboard pages where there are multiple portlets and the page layout can be personalized. The feature is allowed by default on the dashboard, but can be turned off by setting the value in the configuration file to false. The following is a snippet of the default object configuration file ( jboss-portal.sar/conf/data/default-object.xml ), which illustrates the enabling of the feature. Please note that this can also be configured using the administration console user interface of the JBoss server. <deployment> <if-exists>keep</if-exists> <context> <context-name>dashboard</context-name> <properties> ... <!-- Set the dnd property --> <property> <name>theme.dyna.dnd_enabled</name> <value>true</value> </property> ... </properties> </context></deployment> <name>theme.dyna.dnd_enabled</name> value enables or disables the drag-and-drop behavior. Partial content refresh One of the most expensive processes in a portal is the refresh of portlets when the page is generated. For every user action on a page, the portal calls all of the portlet methods in a serial, but non-specific order, which involves a significant amount of time and server-side processing. Partial content refresh support mitigates these issues to a large extent with an effective use of client-server asynchronous communication. When the state of a single portlet changes, a partial content refresh facilitates the update and refresh of only that portlet, instead of for all of the portlets on the page. This prevents the regeneration of the whole page and the initialization of all of the portlets on the page. The following image illustrates the partial content refresh flow:   The partial refresh capability is compatible with the JSR-168 portlet API, which allows for programmatic update of portlet states during runtime. Partial refreshes can be enabled through portal object configuration or through configuration at the default server level.
Read more
  • 0
  • 0
  • 2066
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-primer-agi-asterisk-gateway-interface
Packt
16 Oct 2009
2 min read
Save for later

A Primer to AGI: Asterisk Gateway Interface

Packt
16 Oct 2009
2 min read
How does AGI work Let's examine the following diagram: As the previous diagram illustrates, an AGI script communicates with Asterisk via two standard data streams—STDIN (Standard Input) and STDOUT (Standard Output). From the AGI script point-of-view, any input coming in from Asterisk would be considered STDIN, while output to Asterisk would be considered as STDOUT. The idea of using STDIN/STDOUT data streams with applications isn't a new one, even if you're a junior level programmer. Think of it as regarding any input from Asterisk with a read directive and outputting to Asterisk with a print or echo directive. When thinking about it in such a simplistic manner, it is clear that AGI scripts can be written in any scripting or programming language, ranging from BASH scripting, through PERL/PHP scripting, to even writing C/C++ programs to perform the same task. Let's now examine how an AGI script is invoked from within the Asterisk dialplan: exten => _X.,1,AGI(some_script_name.agi,param1,param2,param3) As you can see, the invocation is similar to the invocation of any other Asterisk dialplan application. However, there is one major difference between a regular dialplan application and an AGI script—the resources an AGI script consumes.While an internal application consumes a well-known set of resources from Asterisk, an AGI script simply hands over the control to an external process. Thus, the resources required to execute the external AGI script are now unknown, while at the same time, Asterisk consumes the resources for managing the execution of the AGI script.Ok, so BASH isn't much of a resource hog, but what about Java? This means that the choice of programming language for your AGI scripts is important. Choosing the wrong programming language can often lead to slow systems and in most cases, non-operational systems. While one may argue that the underlying programming language has a direct impact on the performance of your AGI application, it is imperative to learn the impact of each. To be more exact, it's not the language itself, but more the technology of the programming language runtime that is important. The following table tries to distinguish between three programming languages' families and their applicability to AGI development.
Read more
  • 0
  • 0
  • 6544

article-image-competitive-service-and-contract-management-sap-business-one-implementation-part-2
Packt
16 Oct 2009
8 min read
Save for later

Competitive Service and Contract Management in SAP Business ONE Implementation: Part 2

Packt
16 Oct 2009
8 min read
In the first half of this 2-part article series, we looked at the service module so as to evaluate potential actions that are triggered, based on service-related information. We also introduced a concept which explained how to utilize the service module features to establish a guaranteed response time for customers. We also learnt about : Key terms - The common terminology related to service management were covered. Although nothing major , we went about learning what the terms entail with regards to the SAP system. Service module core functions – In this section, the available functions and features were put into perspective—what is available and how much we can expect from it.  You also learnt what service operations mean. Case study and your own project – The available features of the service module were implemented for the case study. By doing so, knowledge was provided to implement the service module in your own business. We also reviewed some guidelines which enabled you to translate the case study implementation into a set of activities for your own project. Let's begin with Service reports. Service reports The crucial element of each module is the information that can easily be extracted for reporting purposes. SAP provides a series of canned reports for the service module. The Service Calls report provides information about service call activities based on the selected criteria. You can filter this report by timeframe of service call creation and also by resolution time. Additional filter ranges are available for Customer Code, Handled By, Item, and also Queue ID. In addition, the report allows filtering by Problem Type, Priority, Call Type, Origin, Call Status, and Overdue Calls. You can see that there is a wide range of options to obtain information. It is important to note that reporting can utilize the information only if all of the data is properly collected using the SAP forms. In case no options are selected for filtering, the report defaults to select all of the available information. The following additional service reports are available and have almost identical filtering capabilities as the service calls report: Service Calls by Queue, Response Time by Assigned to, Average Closure Time. The Service Contracts report(seen below) helps you manage the status of all maintenance contracts. If you've ever had to manage maintenance contracts with customers, you will appreciate the ease of obtaining the information here. You can filter this report by Customer Code, Start Date Range, End Date Range and Termination Date Range. In addition, this report can be further filtered by Contract Type, Contract Status, and Service Type. The customer equipment card report allows information to be obtained about items sold to customers based on serial number tracking. Each serial number has its own contract with expiration which is usually based on the purchase date. This report is able to be filtered by customer and item code. In addition, a more global filter can be used such as item group. The Service Monitor report provides a more real-time view of the service pipeline. We already covered this report in the previous section. Finally, My Reports includes My Service Calls, My Open Service Calls, and My Overdue Service Calls. Those reports conveniently filter the information based on the current login name. Therefore, if you run the report, you will only see information that is relevant for you based on the login. Limitations I have already mentioned that you can look at SAP Business ONE as the operating system for your business. You can use industry add-ons to seamlessly transform the standard features into an industry solution that is specific to your requirements. Therefore, let's evaluate some add-ons I've worked with that are related to the service module—specifically, the Enprise Job Costing module and the solution from Navigator called ServiceONE. By looking at these add-ons, we can also learn the limitations of the standard service module. For example, since the Navigator promises to have all of the information available in one view, we realize that in SAP, we sometimes need to jump to different forms to get where we wanted to be initially. Let's further evaluate the features of these add-ons. The Enprise Job Costing solution introduces a web-based timesheet. This is an obvious feature that is not directly available in the SAP standard configuration. First, I will look at the Navigator solution and will then follow the Enprise offering. Often, there is more than one add-on providing industry-specific features. You then need to evaluate both solutions and decide which one best fi ts your requirements. Please note that I am presenting the add-on features to better define the limitations of the SAP Standard Business ONE features. Job Costing add-on by Enprise The Enprise Job Costing add-on is one of the first industry-specific solutions that gained widespread adoption as a standard for companies that required a detailed job costing solution. The advantage of this solution is that it is based on true expertise in the job costing area as it relates to the SAP service module. Let's look at a scenario that is very common for companies that work in the service industry and require what is known as job costing. However, I would first like to take the opportunity to explain job costing a bit. Job costing allows the profit and loss for specific services provided to be calculated. For example, if you have a company that sends out technicians to customer sites for performing equipment repairs, you need to make sure that the invoiced amount exceeds the cost you incur. The following workflow may be common in this environment: Serialized items are delivered to customers with each having a warranty contract that may or may not include services, parts, and replacements. Services may be performed on serialized items delivered by you or by another company. A service call may lead to a proposal (job) which will then be ordered. Technicians may use a timesheet to report the status and time. Timesheet entries must be possible via a mobile device or the Web. Furthermore, time entered needs to be approved before it is relevant for invoicing. A job may lead to subjobs that require unique management of related costs. As the number of jobs increase, you will require "work in progress" reporting. Estimating a job is crucial. Therefore, technicians need to be able to create estimates. It must then be possible to translate those estimates into orders and contracts. As services may require replacement parts, a feature is required that allows optimized picking of relevant items for a specific job. Complex jobs require milestone payments. This needs to be implemented in the contracts. The invoicing system needs to be integrated with the way services are completed. For example, milestone payments, fixed priced billing, and partial invoicing are common requirements in the service industry. The Enprise Job Costing add-on resides in its own menu item called Job Costing. As you can see below, the menu items are well defined and provide a quick overview of the available features. In addition, it is important to note that the features seamlessly appear within the SAP interface: By selecting the Job Entry form, the powerful features come to light. As you can see in the following screenshot, the form allows searching jobs based on Status,Type, Properties, Category, and Entered By. The resulting list is shown in the lower pane. We can use this interface to search for specific jobs, and then click on the Bulk Invoice button as highlighted in the screenshot. This automates the invoicing process based on a clear, uncluttered form. Please note that we do not need to jump between multiple forms. The Direct Time Entry form(seen below) is basically a timesheet. Therefore, technicians can use this to enter the time they spend on projects. Please note the buttons in the lower right that allow importing from the Web and also from an Excel clipboard. Enprise provides a web-based timesheet from which we can import data. However, it is important to note that we can also import from an Excel clipboard. This way, we can use the date that technicians entered in their laptops. The contract list provides a link where the Enprise-enhanced contract management surfaces: The contract management allows milestones for a contract. Each milestone to be established could lead to a milestone payment. In addition, we can directly jump to the related invoices by using the Show Invoices button: Enprise has adopted the concept of master data. For this purpose, the Job Master Data form was established. This is consistent with the SAP concept. Each job is defined and configured with specific parameters, which later drive the transactions that are based on this master data. For example, we can define the job parameters alongside a list of subjobs. In addition, documents can be attached as attachments: Advanced service functionality using ServiceONE by Navigator Navigator provides a wide range of valuable add-ons. Each add-on is valuable. However, the key advantage of Navigator is the comprehensive portfolio of add-ons the cover almost all aspects of SAP Business ONE. In particular, the fact that Navigator also provides a mobile solution, which connects handheld computers with SAP Business ONE, extends the reach of the available functionality beyond the boundaries of the SAP client interface. Therefore, a mobile field service does not need to use a web-based timesheet, but could directly interact using mobile devices. However, you may need to purchase another add-on to accomplish this.
Read more
  • 0
  • 0
  • 2641

article-image-optimizing-lighttpd
Packt
16 Oct 2009
5 min read
Save for later

Optimizing Lighttpd

Packt
16 Oct 2009
5 min read
If our Lighttpd runs on a multi-processor machine, it can take advantage of that by spawning multiple versions of itself. Also, most Lighttpd installations will not have a machine to themselves; therefore, we should not only measure the speed but also its resource usage. Optimizing Compilers: gcc with the usual settings (-O2) already does quite a good job of creating a fast Lighttpd executable. However, -O3 may nudge the speed up a tiny little bit (or slow it down, depending on our system) at the cost of a bigger executable system. If there are optimizing compilers for our platform (for example, Intel and Sun Microsystems each have compilers that optimize for their CPUs), they might even give another tiny speed boost. If we do not want to invest money in commercial compilers, but maximize on what gcc has to offer, we can use Acovea, which is an open source project that employs genetic algorithms and trial-and-error to find the best individual settings for gcc on our platform. Get it from http://www.coyotegulch.com/products/acovea/ Finally, optimization should stop where security (or, to a lesser extent, maintainability) is compromised. A slower web server that does what we want is way better than a fast web server obeying the commands of a script kiddie. Before we optimize away blindly, we better have a way to measure the "speed". A useful measure most administrators will agree with is "served requests per second". http_load is a tool to measure the requests per second. We can get it from http://www.acme.com/software/http_load/. http_load is very simple. Give it a site to request, and it will flood the site with requests, measuring how many are served in a given amount of time. This allows a very simplistic approach to optimizing Lighttpd: Tweak some settings, run http_load with a sufficient realistic scenario, and see if our Lighttpd handles more or less requests than before. We do not yet know where to spend time optimizing. For this, we need to make use of timing log instrumentation that has been included with Lighttpd 1.5.0 or even use a profiler to see where the most time is spent. However, there are some "big knobs" to turn that can increase performance, where http_load will help us find a good setting. Installing http_load http_load can be downloaded as a source .tar file (which was named .tar.gz for me, though it is not gzipped). The version as of this writing is 12Mar2006. Unpack it to /usr/src (or another path by changing the /usr/src) with: $ cd /usr/src && tar xf /path/to/http_load-12Mar2006.tar.gz$ cd http_load-12Mar2006 We can optionally add SSL support. We may skip this if we do not need it. To add SSL support we need to find out where the SSL libs and includes are. I assume they are in /usr/lib and /usr/include, respectively, but they may or may not be the same on your system. Additionally, there is a "SSL tree" directory that is usually in /usr/ssl or /usr/local/ssl and contains certificates, revocation lists, and so on. Open the Makefile with a text editor and look at line 11 to 14, which reads: #SSL_TREE = /usr/local/ssl#SSL_DEFS = -DUSE_SSL#SSL_INC = -I$(SSL_TREE)/include#SSL_LIBS = -L$(SSL_TREE)/lib -lssl -lcrypto Change them to the following (assuming the given directories are correct): SSL_TREE = /usr/sslSSL_DEFS = -DUSE_SSLSSL_INC = -I/usr/includeSSL_LIBS = -L/usr/lib -lssl -lcrypto Now compile and install http_loadwith the following command: $ make all install Now we're all set to load-test our Lighttpd. Running http_load tests We just need a URL file, which contains URLs that lead to the pages our Lighttpd serves. http_load will then fetch these pages at random as long as, or as often as we ask it to. For example, we may have a front page with links to different articles. We can just start putting a link to our front page into the URL file, which we will name urls to get started; for example, http://localhost/index.html. Note that the file just contains URLs, nothing less, nothing more (for example, http_load does not support blank lines). Now we can make our first test run: $ http_load -parallel 10 -seconds 60 urls This will run for one minute and try to open 10 connections per second. Let's see if our Lighttpd keeps up: 343 fetches, 10 max parallel, 26814 bytes, in 60 seconds78.1749 mean bytes/connection5.71667 fetches/sec, 446.9 bytes/secmsecs/connect: 290.847 mean, 9094 max,15 minmsecs/first-response: 181.902 mean, 9016 max, 15 minHTTP response codes: code 200 - 327   As we can see, it does. http_load needs one of the two start conditions and one of the two stop conditions plus a URL file to run. We can create the URL file manually or crawl our document root(s) with the following python script called crawl.py: #!/usr/bin/python#run from document root, pipe into URLs file. For example:# /path/to/docroot$ crawl.py > urlsimport os, re, syshostname = "http://localhost/"for (root, dirs, files) in os.walk("."): for name in files: filepath = os.path.join(root, name) print re.sub("./", hostname, filepath)   You can download the crawl.oy file from http://www.packtpub.com/files/code/2103_Code.zip. Capture the output into a file to use as URL file. For example, start the script from within our document root with: $ python crawl.py > urls This will give us a urls file, which will make http_load try to get all files (given that we have specified enough requests). Then we can start http_load as discussed in the preceding example. http_load takes the following options:  
Read more
  • 0
  • 0
  • 7278

article-image-working-drupal-audio-flash-part-2
Packt
16 Oct 2009
6 min read
Save for later

Working with Drupal Audio in Flash (part 2)

Packt
16 Oct 2009
6 min read
Although there are a handful of controls that we can add to this custom audio player, this section will demonstrate the concept by adding the most basic control for multimedia, which is the play and pause buttons. Adding a play and pause button To begin, we will need to first move and resize our title field within our Flash application, so that it can hold more text than "Hello World". We can then make room for some new controls that will be used to control the playback of our audio file. Again, the design of each of these components is subjective, but what is important is the MovieClip instance hierarchy, which will be used within our ActionScript code. Before we begin, we will need to create a new layer in our TIMELINE that will be used to place all AudioPlayer objects. We will call this new layer player: Creating a base button MovieClip Our base button will simply be a rounded rectangle, which we will then add some gradients to, so as to give it depth. We can do this by first creating a rounded rectangle with a vertical linear gradient fill as follows: We can now give it some very cool depth by adding a smaller rounded rectangle within this one, and then orient the same gradient horizontally. An easy way to do this is to copy the original shape and paste it as a new shape. Once we have a new copy of our original rounded rectangle, we can navigate to Modify | Shape | Expand fill, where we will then select Inset, change our Distance to 4px, and then click on OK. After doing this, you will realize how such a simple contrast in gradients can really bring out the shape. After we have our new button shape, we will then need to create a new MovieClip, so that we can reuse this button for both the play and pause buttons. To do this, simply select both the rounded rectangle regions, and then choose Modify | Convert to Symbol in the Flash menu. We are going to call this new movie clip mcButton. Now that we have a base button MovieClip, we can now add the play and pause symbols to complete the play and pause buttons. Adding the PlayButton movie clip The first button that we will create is the play button, which simply consists of a sideways triangle (icon) with the button behind it. To do this, we will first create a new movie clip that will hold the button we just created, and the play icon. We can do this by first clicking on the mcButton movie clip, and then creating a new movie clip from that by selecting Modify | Convert to Symbol. We will call our new movie clip mcPlayButton. What we are really doing here is creating a parent movie clip for our mcButton, which will allow us to add new specific elements. For the play button, we simply want to add a play symbol. To do this, we first want to make sure that we are within the mcPlayButton movie clip by double-clicking on this symbol, so that our breadcrumb at the top of the stage looks as follows: Our next task is to modify our timeline within this movie clip so that we can separate the icon from the button. We can do this by creating two new layers within our timeline, called button (which will hold our button) and icon (which we will create in the next section). We are now ready to start drawing the play icon. Drawing a play icon To draw a Play icon, we will need to first select the PolyStar Tool by clicking and holding on the tool until you can select the PolyStar Tool. This tool will allow us to create a triangle, which we will use for the play icon in our play button. But before we can start drawing, we need to first set up the PolyStar Tool so that it will draw a triangle. We can do this by clicking on the Options button within the Properties tab, which will then bring up a dialog, where we can tell it to draw a polygon with three sides (triangle). After we click on OK, we will then need to change the fill color of this triangle, so that it is visible on our button. We will just change the fill color to Black. We can then move our cursor onto the stage where the button is, and then draw our triangle in the shape of a play button icon. Remember, if you do not like the shape of what you made, you can always tweak it using the transform tool. When we are done, we should have something that resembles a play button! Our next task is to create a pause button. Since we have already created the play button, which is similar to the pause button except for the icon, we can use a handy tool in Flash that will let us duplicate our play button, and then modify our duplication for the pause button icon. Creating a pause button from the play button In order to create our pause button, we will first need to duplicate our play button into a new movie clip, where we can change the icon from play to pause. To do this, we will first direct our attention to the library section of our Flash IDE, which should show us all of the movie clips that we have created so far. We can find the LIBRARY by clicking on the button on the right-hand side of our workspace. To create a duplicate, we will now right-click on the mcPlayButton movie clip, and then select the option Duplicate. This will then bring up a dialog very similar to the dialog when we created new symbols, but this time, we are defining a new movie clip name that will serve as a duplicate for the original one. We will call our new movie clip duplicate mcPauseButton. Now that we have created our duplicate movie clip, the next task is to change the icon within the pause button. We can do this by opening up our mcPauseButton movie clip by double-clicking on that name within the Library. At this point, we can now change the icon of our pause button without running any risk of also modifying the play button (since we created a duplicate). When we are done, we should have a complete pause button. We now have play a nd pause buttons that we will use to link to our AudioPlayer class.
Read more
  • 0
  • 0
  • 3493
article-image-java-data-objects-and-service-data-objects-soa
Packt
16 Oct 2009
11 min read
Save for later

Java Data Objects and Service Data Objects in SOA

Packt
16 Oct 2009
11 min read
JDO Java Data Objects (JDO) is a complementing standard of accessing data from your data store using a standard interface-based abstraction model of persistence in java. The original JDO (JDO 1.0) specification is quite old and is based on Java Specification Request 12 (JSR 12). The current major version of JDO (JDO 2.0) is based on JSR 243. The original specifications were done under the supervision of Sun and starting from 2.0, the development of the API and the reference implementation happens as an Apache open-source project. Why JDO? We have been happily programming to retrieve data from relational stores using JDBC, and now the big question is do we need yet another standard, JDO? If you think that as software programmers you need to provide solutions to your business problems, it makes sense for you to start with the business use cases and then do a business analysis at the end of which you will come out with a Business Domain Object Model (BDOM). The BDOM will drive the design of your entity classes, which are to be persisted to a suitable data store. Once you design your entity classes and their relationship, the next question is should you be writing code to create tables, and persist or query data from these tables (or data stores, if there are no tables). I would like to answer 'No' for this question, since the more code you write, the more are the chances of making errors, and further, developer time is costly. Moreover, today you may write JDBC for doing the above mentioned "technical functionalities", and tomorrow you may want to change all your JDBC to some other standard since you want to port your data from a relational store to a different persistence mechanism. To sum up, let us list down a few of the features of JDO which distinguishes itself from other similar frameworks. Separation of Concerns: Application developers can focus on the BDOM and leave the persistence details (storage and retrieval) to the JDO implementation. API-based: JDO is based on a java interface-based programming model. Hence all persistence behavior including most commonly used features of OR mapping is available as metadata, external to your BDOM source code. We can also Plug and Play (PnP) multiple JDO implementations, which know how to interact well with the underlying data store. Data store portability: Irrespective of whether the persistent store is a relational or object-based file, or just an XML DB or a flat file, JDO implementations can still support the code. Hence, JDO applications are independent of the underlying database. Performance: A specific JDO implementation knows how to interact better with its specific data store, which will improve performance as compared to developer written code. J2EE integration: JDO applications can take advantage of J2EE features like EJB and thus the enterprise features such as remote message processing, automatic distributed transaction coordination, security, and so on. JPOX—Java Persistent Objects JPOX is an Apache open-source project, which aims at a heterogeneous persistence solution for Java using JDO. By heterogeneous we mean, JPOX JDO will support any combination of the following four main aspects of persistence: Persistence Definition: The mechanism of defining how your BDOM classes are to be persisted to the data store. Persistence API: The programming API used to persist your BDOM objects. Query Language: The language used to find objects due to certain criteria. Data store: The underlying persistent store you are persisting your objects to. JDO Sample Using JPOX In this sample, we will take the familiar Order and LineItems scenario, and expand it to have a JDO implementation. It is assumed that you have already downloaded and extracted the JPOX libraries to your local hard drive. BDOM for the Sample We will limit our BDOM for the sample discussion to just two entity classes, that is, OrderList and LineItem. The class attributes and relationships are shown in the following screenshot: The BDOM illustrates that an Order can contain multiple line items. Conversely, each line item is related to one and only one Order. Code BDOM Entities for JDO The BDOM classes are simple entity classes with getter and setter methods for each attribute. These classes are then required to be wired for JDO persistence capability in a JDO specific configuration file, which is completely external to the core entity classes. OrderList.java OrderList is the class representing the Order, and is having a primary key attribute that is number. public class OrderList{ private int number; private Date orderDate; private Set lineItems; // other getter & setter methods go here // Inner class for composite PK public static class Oid implements Serializable{ public int number; public Oid(){ } public Oid(int param){ this.number = param; } public String toString(){ return String.valueOf(number); } public int hashCode(){ return number; } public boolean equals(Object other){ if (other != null && (other instanceof Oid)){ Oid k = (Oid)other; return k.number == this.number; } return false; } } } LineItem.java LineItem represents each item container in the Order. We don't explicitly define a primary key for LineItem even though JDO will have its own mechanism to do that. public class LineItem{ private String productId; private int numberOfItems; private OrderList orderList; // other getter & setter methods go here } package.jdo JDO requires an XML configuration file, which defines the fields that are to be persisted and to what JDBC or JDO wrapper constructs should be mapped to. For this, we can create an XML file called package.jdo with the following content and put it in the same directory where we have the entities. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd"> <jdo> <package name="com.binildas.jdo.jpox.order"> <class name="OrderList" identity-type="application" objectid-class="OrderList$Oid" table="ORDERLIST"> <field name="number" primary-key="true"> <column name="ORDERLIST_ID"/> </field> <field name="orderDate"> <column name="ORDER_DATE"/> </field> <field name="lineItems" persistence-modifier="persistent" mapped-by="orderList"> <collection element-type="LineItem"> </collection> </field> </class> <class name="LineItem" table="LINEITEM"> <field name="productId"> <column name="PRODUCT_ID"/> </field> <field name="numberOfItems"> <column name="NUMBER_OF_ITEMS"/> </field> <field name="orderList" persistence-modifier="persistent"> <column name="LINEITEM_ORDERLIST_ID"/> </field> </class> </package> </jdo> jpox.PROPERTIES In this sample, we will persist our entities to a relational database, Oracle. We specify the main connection parameters in jpox.PROPERTIES file. javax.jdo.PersistenceManagerFactoryClass=org.jpox.jdo.JDOPersistenceManagerFactory javax.jdo.option.ConnectionDriverName=oracle.jdbc.driver.OracleDriver javax.jdo.option.ConnectionURL=jdbc:oracle:thin:@127.0.0.1:1521:orcl javax.jdo.option.ConnectionUserName=scott javax.jdo.option.ConnectionPassword=tiger org.jpox.autoCreateSchema=true org.jpox.validateTables=false org.jpox.validateConstraints=false Main.java This class contains the code to test the JDO functionalities. As shown here, it creates two Orders and adds few line items to each order. First it persists these entities and then queries back these entities using the id. public class Main{ static public void main(String[] args){ Properties props = new Properties(); try{ props.load(new FileInputStream("jpox.properties")); } catch (Exception e){ e.printStackTrace(); } PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props); PersistenceManager pm = pmf.getPersistenceManager(); Transaction tx = pm.currentTransaction(); Object id = null; try{ tx.begin(); LineItem lineItem1 = new LineItem("CD011", 1); LineItem lineItem2 = new LineItem("CD022", 2); OrderList orderList = new OrderList(1, new Date()); orderList.getLineItems().add(lineItem1); orderList.getLineItems().add(lineItem2); LineItem lineItem3 = new LineItem("CD033", 3); LineItem lineItem4 = new LineItem("CD044", 4); OrderList orderList2 = new OrderList(2, new Date()); orderList2.getLineItems().add(lineItem3); orderList2.getLineItems().add(lineItem4); pm.makePersistent(orderList); id = pm.getObjectId(orderList); System.out.println("Persisted id : "+ id); pm.makePersistent(orderList2); id = pm.getObjectId(orderList2); System.out.println("Persisted id : "+ id); orderList = (OrderList) pm.getObjectById(id); System.out.println("Retreived orderList : " + orderList); tx.commit(); } catch (Exception e){ e.printStackTrace(); if (tx.isActive()){ tx.rollback(); } } finally{ pm.close(); } } } Build and Run the JDO Sample You can download the required code for this article from http://www.packtpub.com/files//code/3216_Code.zip. Unzip the file and the code of our interest is in the folder 3216_04_Code. There is also a README.txt file, which gives detailed steps to build and run the samples. Since we use Oracle to persist entities, we need the following two libraries in the classpath: jpox-rdbms*.jar classes12.jar We require a couple of other libraries too which are specified in the build.xml file. Download these libraries and change the path in examples.PROPERTIES accordingly. To build the sample, first bring up your database server. Then to build the sample in a single command, it is easy for you to go to ch04jdo folder and execute the following command. cd ch04jdo ant The above command will execute the following steps: First it compiles the java source files Then for every class you persist, use JPOX libraries to enhance the byte code. As the last step, we create the required schema in the data store. To run the sample, execute: ant run You can now cross check whether the entities are persisted to your data store. This is as shown in the following screenshot where you can see that each line item is related to the parent order by the foreign key.   Data Services Good that you now know how to manage the basic data operations in a generic way using JDO and other techniques. By now, you also have good hands-on experience in defining and deploying web services. We all appreciate that web services are functionalities exposed in standard, platform, and technology neutral way. When we say functionality we mean the business use cases translated in the form of useful information. Information is always processed out of data. So, once we retrieve data, we need to process it to translate them into information. When we define SOA strategies at an enterprise level, we deal with multiple Line of Business (LOB) systems; some of them will be dealing with the same kind of business entity. For example, a customer entity is required for a CRM system as well as for a sales or marketing system. This necessitates a Common Data Model (CDM), which is often referred to as the Canonical Data Model or Information Model. In such a model, you will often have entities that represent "domain" concepts, for example, customer, account, address, order, and so on. So, multiple LOB systems will make use of these domain entities in different ways, seeking different information-based on the business context. OK, now we are in a position to introduce the next concept in SOA, which is "Data Services". Data Services are specialization of web services which are data and information oriented. They need to manage the traditional CRUD (Create, Read, Update, and Delete) operations as well as a few other data functionalities such as search and information modeling. The Create operation will give you back a unique ID whereas Read, Update, and Delete operations are performed on a specific unique ID. Search will usually be done with some form of search criteria and information modeling, or retrieval happens when we pull useful information out of the CDM, for example, retrieving the address for a customer. The next important thing is that no assumptions should be made that the data will be in a java resultset form or in a collection of transfer object form. Instead, you are now dealing with data in SOA context and it makes sense to visualize data in XML format. Hence, XML Schema Definition (XSDs) can be used to define the format of your requests and responses for each of these canonical data definitions. You may also want to use ad hoc queries using XQuery or XPath expressions, similar to SQL capabilities on relational data. In other words, your data retrieval and data recreation for information processing at your middle tier should support XML tools and mechanisms, and should also support the above six basic data operations. If so, higher level of abstractions in the processing tier can make use of the above data services to provide Application Specialization capabilities, specialized for the LOB systems. To make the concept clear, let us assume that we need to get the order status for a particular customer (getCustomerOrderStatus()) which will take the customer ID argument. The data services layer will have a retrieve operation passing the customer ID and the XQuery or the XPath statement will obtain the requested order information from the retrieved customer data. High level processing layers (such as LOB service tiers) can use high-level interface (for example, our getCustomerOrderStatus operation) of the Application Specialization using a web services (data services) interface and need not know or use XQuery or XPath directly. The underlying XQuery or XPath can be encapsulated, reused, and optimized.
Read more
  • 0
  • 0
  • 10035

article-image-exceptions-and-logging-apache-struts-2
Packt
16 Oct 2009
8 min read
Save for later

Exceptions and Logging in Apache Struts 2

Packt
16 Oct 2009
8 min read
Handling exceptions in Struts 2 Struts 2 provides a declarative exception handling mechanism that can be configured globally (for an entire package), or for a specific action. This capability can reduce the amount of exception handling code necessary inside actions under some circumstances, most notably when underlying systems, such as our services, throw runtime exceptions (exceptions that we don't need to wrap in a try/catch or declare that a method throws). To sum it up, we can map exception classes to Struts 2 results. The exception handling mechanism depends on the exception interceptor. If we modify our interceptor stack, we must keep that in mind. In general, removing the exception interceptor isn't preferred. Global exception mappings Setting up a global exception handler result is as easy as adding a global exception mapping element to a Struts 2 configuration file package definition and configuring its result. For example, to catch generic runtime exceptions, we could add the following: <global-exception-mappings><exception-mapping result="runtime"exception="java.lang.RuntimeException"/></global-exception-mappings> This means that if a java.lang.RuntimeException (or a subclass) is thrown, the framework will take us to the runtime result. The runtime result may be declared in an element, an action configuration, or both. The most specific result will be used. This implies that an action's result configuration might take precedence over a global exception mapping. For example, consider the global exception mapping shown in the previous code snippet. If we configure an action as follows, and a RuntimeException is thrown, we'll see the locally defined runtime result, even if there is a global runtime result. <action name="except1"class="com.packt.s2wad.ch09.examples.exceptions.Except1"><result name="runtime">/WEB-INF/jsps/ch9/exceptions/except1-runtime.jsp</result>... This can occasionally lead to confusion if a result name happens to collide with a result used for an exception. However, this can happen with global results anyway (a case where a naming convention for global results can be handy). Action-specific exception mappings In addition to overriding the result used for an exception mapping, we can also override a global exception mapping on a per-action basis. For example, if an action needs to use a result named runtime2 as the destination of a RuntimeException, we can configure an exception mapping specific to that action. <action name="except2"class="com.packt.s2wad.ch09.examples.exceptions.Except1"><exception-mapping result="runtime2"exception="java.lang.RuntimeException"/>... As with our earlier examples, the runtime2 result may be configured either as a global result or as an action-specific result. Accessing the exception We have many options regarding how to handle exceptions. We can show the user a generic "Something horrible has happened!" page, we can take the user back and allow them to retry the operation or refill the input form, and so on. The appropriate course of action depends on the application and, most likely, on the type of exception. We can display exception-specific information as well. The exception interceptor pushes an exception encapsulation object onto the stack with the exception and exceptionStack properties. While the stack trace is probably not appropriate for user-level error pages, the exception can be used to help create a useful error message, provide I18N property keys for messages (or values used in messages), suggest possible remedies, and so on. The simplest example of accessing the exception property from our JSP is to simply display the exception message. For example, if we threw a RuntimeException, we might create it as follows: throw newRuntimeException("Runtime thrown from ThrowingAction"); Our exception result page, then, could access the message using the usual property tag (or JSTL, if we're taking advantage of Struts 2's custom request processor): <s:property value="exception.message"/> The underlying action is still available on the stack—it's the next object on the value stack. It can be accessed from the JSP as usual, as long as we're not trying to access properties named exception or exceptionStack, which would be masked by the exception holder. (We can still access an action property named exception using OGNL's immediate stack index notation—[1].exception.) Architecting exceptions and exception handling We have pretty good control over what is displayed for our application exceptions. It is customizable based on exception type, and may be overridden on a per-action basis. However, to make use of this flexibility, we require a well-thought-out exception policy in our application. There are some general principles we can follow to help make this easier. Checked versus unchecked exceptions Before we start, let's recall that Java offers two main types of exceptions—checked and unchecked. Checked exceptions are exceptions we declare with a throws keyword or wrapped in a try/catch block. Unchecked exceptions are runtime exceptions or a subclass. It isn't always clear what type we should use when writing our code or creating our exceptions. It's been the subject of much debate over the years, but some guidelines have become apparent. One clear thing about checked exceptions is that they aren't always worth the aggravation they cause, but may be useful when the programmer has a reasonable chance of recovering from the exception. One issue with checked exceptions is that unless they're caught and wrapped in a more abstract exception (coming up next), we're actually circumventing some of the benefits of encapsulation. One of the benefits being circumvented is that when exceptions are declared as being thrown all the way up a call hierarchy, all of the classes involved are forced to know something about the class throwing the exception. It's relatively rare that this exposure is justifiable. Application-specific exceptions One of the more useful exception techniques is to create application-specific exception classes. A compelling feature of providing our own exception classes is that we can include useful diagnostic information in the exception class itself. These classes are like any other Java class. They can contain methods, properties, and constructors. For example, let's assume a service that throws an exception when the user calling the service doesn't have access rights to the service. One way to create and throw this exception would be as follows: throw new RuntimeException("User " + user.getId()+ " does not have access to the 'update' service."); However, there are some issues with this approach. It's awkward from the Struts 2's standpoint. Because it's a RuntimeException, we have only one option for handling the exception—mapping a RuntimeException to a result. Yes, we could map the exception type per-action, but that gets unwieldy. It also doesn't help if we need to map two different types of RuntimeExceptions to two different results. Another potential issue would arise if we had a process that examined exceptions and did something useful with them. For example, we might send an email with user details based on the above exception. This would amount to parsing the exception message, pulling out the user ID, and using it to get user details for inclusion in the email. This is where we'd need to create an exception class of our own, subclassed from RuntimeException. The class would have encapsulated exception related information, and a mechanism to differentiate between the different types of exceptions. A third benefit comes when we wrap lower-level exceptions—for example, a Spring-related exception. Rather than create a Spring dependency up the entire call chain, we'd wrap it in our own exception, abstracting the lower-level exception. This allows us to change the underlying implementation and aggregate differing exception types under one (or more) application-specific exception. One way of creating the above scenario would be to create an exception class that takes a User object and a message as its constructor arguments: package com.packt.s2wad.ch09.exceptions;public class UserAccessException extends RuntimeException {private User user;private String msg;public UserAccessException(User user, String msg) {this.user = user;this.msg = msg;}public String getMessage() {return "User " + user.getId() + " " + msg;}} We can now create an exception mapping for a UserAccessException (as well as a generic RuntimeException if we need it). In addition, the exception carries along with it the information needed to create useful messages: throw new UserAccessException(user,"does not have access to the 'update' service."); "Self-documenting" of code could be made even safer, in the sense of ensuring that it's only used in the ways in which it is intended. We could add an enum to the class to encapsulate the reasons the exception can be thrown, including the text for each reason. We'll add the following inside  our UserAccessException: public enum Reason {NO_ROLE("does not have role"),NO_ACCESS("does not have access");private String message;private Reason(String message) {this.message = message;}public String getMessage() { return message; }}; We'll also modify the constructor and getMessage() method to use the new Reason enumeration. public UserAccessException(User user, Reason reason) {this.user = user;this.reason = reason;}public String getMessage() {return String.format("User %d %s.",user.getId(), reason.getMessage());} Now, when we throw the exception, we explicitly know that we're using the exception class correctly (at least type-wise). The string message for each of the exception reasons is encapsulated within the exception class itself. throw new UserAccessException(user,UserAccessException.Reason.NO_ACCESS); With Java 5's static imports, it might make even more sense to create static helper methods in the exception class, leading to the concise, but understandable code: throw userHasNoAccess(user);
Read more
  • 0
  • 1
  • 10849

article-image-using-graphs-manage-networks-and-devices-cacti-08
Packt
16 Oct 2009
4 min read
Save for later

Using Graphs to Manage Networks and Devices with Cacti 0.8

Packt
16 Oct 2009
4 min read
Creating graphs If you are familiar with RRDTool, then you know Cacti is designed to harness the power of RRDTool's data storage and graphing functionality. If you are not, don't worry—Cacti will create graphs without extensive configuration input from users. Built-in graph templates will make your life easier, so it is not necessary to understand the functionality of each field to create graphs for network-attached devices. Each graph stores different sets of parameters that control different aspects of each graph. If you want to know more about RRDTool, please visit http://oss.oetiker.ch/rrdtool/. At the time of creating graphs, you will face a bit of a stiff learning curve. Stay on course, it will be over soon and you will be able to create graphs for different devices very quickly. Cacti can create graphs for any SNMP-enabled, network-attached devices. This can be a switch, router, server, desktop computer, printer, IPS, UPS, and so on. Initially, we will not talk about the custom template and the data-query script development for any SNMP-enabled devices. Instead, we will use the default options in Cacti. In order to build a custom template, we need to understand the SNMP protocol and command-line tools of the Net-SNMP application suite. Let's create graphs based on the available templates and devices. Adding a device Before we add a graph, we need to add a device for which you want to create the graph. In order to do that, click on Devices under Management. Cacti will open the Devices view panel. It will look like this: If you click Add in the top right-hand corner, it will open a new form to add a new device. The first two fields, Description and Hostname, are both required for the default configuration. The other fields in the Device section (Notes and Disable Device) can be left as is. If your host template exists in the drop-down, be sure to select the template. Since we are starting with an SNMP-enabled device, if you are not sure which template to select, you can select the Generic SNMP-enabled host template. It is important to know that adding a template to a device will not lock down the device to any specific configuration, as graph templates and queries can be added and removed from a device at anytime. The following screenshot shows how the Add a device form looks. If you look closely at the drop-down, there are very few templates. But you can add device-specific templates as required. The following web site has an excellent collection of Cacti scripts and templates. This web site is aimed at providing tips and tricks to Debian users from novice to expert. The owner also collects and updates all sorts of scripts and templates from the Cacti forum for easy access: http://www.debianhelp.co.uk/cactitemplates.htm Device fields definition Every device that we add has different attributes and values. The following table will clarify the attributes. It is wise to understand all the fields before adding a device in Cacti. Fields Descriptions Description Giving host a meaningful name. This name will be shown in the first column of the device view panel. Hostname Fully qualified hostname or IP. If a fully qualified hostname is being used such as linuxbox1.example.com, Dynamic Name Services (DNS) will be used to resolve the hostname. Host Template Host template is responsible for the types of data that need to be gathered from a specific type of host. Notes Adding notes for the host, anything that is specific to the host. Disable Host Check this box to disable all the checks for this device. This means no polling for this device. Downed Device Detection NONE: Disable downed device detection. Ping and SNMP: Perform both tests. SNMP: Perform SNMP check. Ping: Use ping method. Ping Method ICMP Ping: Perform ICMP test. ICMP on Linux/Unix require root privileges. TCP Ping: Perform a TCP test. UDP Ping: Perform UDP test. Ping Port This option is available for only TCP and UDP Ping. Define the port number here and make sure the firewall is not blocking that port. Ping Timeout Value This value is measured in milliseconds. After the defined time, the test will fail. Ping Retry Count Defines how many times Cacti will ping a host before failing. SNMP Version Version 1: Supported by most of the SNMP-enabled devices. One thing you need to remember is that it doesn't support a 64-bit counter. Version 2: This is also known as SNMPv2c. Supported by most of the SNMP-enabled devices. Version 3: Version 3 supports authentication and encryption.
Read more
  • 0
  • 0
  • 4719
article-image-voice-menus-and-ivr-asterisknow
Packt
16 Oct 2009
3 min read
Save for later

Voice Menus and IVR in AsteriskNOW

Packt
16 Oct 2009
3 min read
Four Rules of IVR IVR systems can be hell to use; the main reason for this is that people designing IVR systems tend to complicate their functionality beyond the normal usage scope of a human being. The following four rules will enable you to implement a usable, humanly accessible, and maintainable IVR. Rule 1—Keep it narrow: Your IVR should be kept as simple as possible. Make sure that each of your steps in the IVR environment is not longer than five options. Most IVR users aren't able to remember all the options of an IVR system, when presented with a multitude of IVR options. Rule 2—Keep it shallow: Your IVR system's depth is in direct relation to the complexity of the IVR application. If your application has more than four levels, you need to revise your IVR plan. Most people (including yours truly) become extremely aggravated when confronted with an IVR system that is asking for too much information. Rule 3—Enable escape routes: Always give your IVR user the ability to break out of the IVR flow and talk to a live person. Some people simply can't handle the usage of an IVR system. Rule 4—If it works, don't fix it!: For some reason, companies tend to change their IVR flows every other day to support a new business model. An IVR system that constantly changes is a nightmare for users, as they never get used to the options of the system. If you must perform an update, make sure that your update doesn't affect that system in such a way that the users need to re-learn the system. Voice Menus—AsteriskNOW's IVR Generator AsteriskNOW provides a highly simplistic IVR generator, rightfully named—Voice Menus. The main usage of an IVR in a PBX is the implementation of an "Auto Attendant". Some PBX systems refer to auto-attendant and IVR as two different things. In AsteriskNOW, they are one and the same. At this point, click the Voice Menus link, located on your left-hand main menu. The following should appear on your screen: This interface enables editing, creation, or deletion of voice menus. Each menu is built from a set of operational directives (Steps) and functional keys (Keypress Events). Each voice menu also receives a mandatory name (Name), a form of logical entity description, and an Extension number (optional). The extension number enables PBX extensions or external users to dial into the specific voice menu indicated by the extension number. Voice Menu Steps—The Voice Menu Flow Steps are performed one after the other, in the order they appear on the screen. There are seventeen possible steps, available through the AsteriskNOW GUI. Once a step had been selected, the GUI will change, indicating the requirement for additional fields to be filled. The seventeen available steps are as follows:
Read more
  • 0
  • 0
  • 4754

article-image-measures-and-measure-groups-microsoft-analysis-services-part-1
Packt
15 Oct 2009
12 min read
Save for later

Measures and Measure Groups in Microsoft Analysis Services: Part 1

Packt
15 Oct 2009
12 min read
In this two-part article by Chris Webb, we will look at measures and measure groups, ways to control how measures aggregate up, and how dimensions can be related to measure groups. In this part, will cover useful properties of measures, along with built-in measure aggregation types and dimension calculations. Measures and aggregation Measures are the numeric values that our users want to aggregate, slice, dice and otherwise analyze, and as a result, it's important to make sure they behave the way we want them to. One of the fundamental reasons for using Analysis Services is that, unlike a relational database it allows us to build into our cube design business rules about measures: how they should be formatted, how they should aggregate up, how they interact with specific dimensions and so on. It's therefore no surprise that we'll spend a lot of our cube development time thinking about measures. Useful properties of Measures Apart from the AggregateFunction property of a measure, which we'll come to next, there are two other important properties we'll want to set on a measure, once we've created it. Format string The Format String property of a measure specifies how the raw value of the measure gets formatted when it's displayed in query results. Almost all client tools will display the formatted value of a measure, and this allows us to ensure consistent formatting of a measure across all applications that display data from our cube. A notable exception is Excel 2003 and earlier versions, which can only display raw measure values and not formatted values. Excel 2007 will display properly formatted measure values in most cases, but not all. For instance, it ignores the fourth section of the Format String which controls formatting for nulls. Reporting Services can display formatted values in reports, but doesn't by default; this blog entry describes how you can make it do so:  http://tinyurl.com/gregformatstring. There are a number of built-in formats that you can choose from, and you can also build your own by using syntax very similar to the one used by Visual BASIC for Applications (VBA) for number formatting. The Books Online topic FORMAT_STRING Contents gives a complete description of the syntax used. Here are some points to bear in mind when setting the Format String property: If you're working with percentage values, using the % symbol will display your values multiplied by one hundred and add a percentage sign to the end. Note that only the display value gets multiplied by hundred—the real value of the measure will not be, so although your user might see a value of 98% the actual value of the cell would be 0.98. If you have a measure that returns null values in some circumstances and you want your users to see something other than null, don't try to use a MDX calculation to replace the nulls—this will cause severe query performance problems. You can use the fourth section of the Format String property to do this instead—for example, the following: #,#.00;#,#.00;0;NA will display the string NA for null values, while keeping the actual cell value as null without affecting performance. Be careful while using the Currency built-in format: it will format values with the currency symbol for the locale specified in the Language property of the cube. This combination of the Currency format and the Language property is frequently recommended for formatting measures that contain monetary values, but setting this property will also affect the way number formats are displayed: for example, in the UK and the USA, the comma is used as a thousands separator, but in continental Europe it is used as a decimal separator. As a result, if you wanted to display a currency value to a user in a locale that didn't use that currency, then you could end up with confusing results. The value €100,101 would be interpreted as a value just over one hundred Euros to a user in France, but in the UK, it would be interpreted as a value of just over one hundred thousand Euros. You can use the desired currency symbol in a Format String instead, for example '$#,#.00', but this will not have an effect on the thousands and decimal separators used, which will always correspond to the Language setting. You can find an example of how to change the language property using a scoped assignment in the MDX Script here: http://tinyurl.com/gregformatstring. Similarly, while Analysis Services 2008 supports the translation of captions and member names for users in different locales, unlike in previous versions, it will not translate the number formats used. As a result, if your cube might be used by users in different locales you need to ensure they understand whichever number format the cube is using. Display folders Many cubes have a lot of measures on them, and as with dimension hierarchies, it's possible to group measures together into folders to make it easier for your users to find the one they want. Most, but not all, client tools support display folders, so it may be worth checking whether the one you intend to use does. By default each measure group in a cube will have its own folder containing all of the measures on the measure group; these top level measure group folders cannot be removed and it's not possible to make a measure from one measure group appear in a folder under another measure group. By entering a folder name in a measure's Display Folder property, you'll make the measure appear in a folder underneath its measure group with that name; if there isn't already a folder with that name, then one will be created, and folder names are case-sensitive. You can make a measure appear under multiple folders by entering a semi-colon delimited list of names as follows: Folder One; Folder Two. You can also create a folder hierarchy by entering either a forward-slash / or back-slash delimited list (the documentation contradicts itself on which is meant to be used—most client tools that support display folders support both) of folder names as follows: Folder One; Folder TwoFolder Three. Calculated measures defined in the MDX Script can also be associated with a measure group, through the Associated_Measure_Group property, and with a display folder through the Display_Folder property. These properties can be set either in code or in Form View in the Calculations tab in the Cube Editor: If you don't associate a calculated measure with a measure group, but do put it in a folder, the folder will appear at the same level as the folders created for each measure group. Built-in measure aggregation types The most important property of a measure is AggregateFunction; it controls how the measure aggregates up through each hierarchy in the cube. When you run an MDX query, you can think of it as being similar to a SQL SELECT statement with a GROUP BY clause—but whereas in SQL you have to specify an aggregate function to control how each column's values get aggregated, in MDX you specify this for each measure when the cube is designed. Basic aggregation types Anyone with a passing knowledge of SQL will understand the four basic aggregation types available when setting the AggregateFunction property: Sum is the commonest aggregation type to use, probably the one you'll use for 90% of all the measures. It means that the values for this measure will be summed up. Count is another commonly used property value and aggregates either by counting the overall number of rows from the fact table that the measure group is built from (when the Binding Type property, found on the Measure Source dialog that appears when you click on the ellipses button next to the Source property of a measure, is set to Row Binding), or by counting non-null values from a specific measure column (when Binding Type property is set to Column Binding). Min and Max return the minimum and maximum measure values. There isn't a built-in Average aggregation type—as we'll soon see, AverageOfChildren does not do a simple average—but it's very easy to create a calculated measure that returns an average by dividing a measure with AggregateFunction Sum by one with AggregateFunction Count, for example: CREATE MEMBER CURRENTCUBE.[Measures].[Average Measure Example] ASIIF([Measures].[Count Measure]=0, NULL,[Measures].[Sum Measure]/[Measures].[Count Measure]); Distinct Count The DistinctCount aggregation type counts the number of distinct values in a column in your fact table, similar to a Count(Distinct) in SQL. It's generally used in scenarios where you're counting some kind of key, for example, finding the number of unique Customers who bought a particular product in a given time period. This is, by its very nature, an expensive operation for Analysis Services and queries that use DistinctCount measures can perform worse than those which use additive measures. It is possible to get distinct count values using MDX calculations but this almost always performs worse; it is also possible to use many-to-many dimensions to get the same results and this may perform better in some circumstances; see the section on "Distinct Count" in the "Many to Many Revolution" white paper, available at http://tinyurl.com/m2mrev. When you create a new distinct count measure, BIDS will create a new measure group to hold it automatically. Each distinct count measure needs to be put into its own measure group for query performance reasons, and although it is possible to override BIDS and create a distinct count measure in an existing measure group with measures that have other aggregation types, we strongly recommend that you do not do this. None The None aggregation type simply means that no aggregation takes place on the measure at all. Although it might seem that a measure with this aggregation type displays no values at all, that's not true: it only contains values at the lowest possible granularity in the cube, at the intersection of the key attributes of all the dimensions. It's very rarely used, and only makes sense for values such as prices that should never be aggregated. If you ever find that your cube seems to contain no data even though it has processed successfully, check to see if you have accidentally deleted the Calculate statement from the beginning of your MDX Script. Without this statement, no aggregation will take place within the cube and you'll only see data at the intersection of the leaves of every dimension, as if every measure had AggregateFunction None. Semi-additive aggregation types The semi-additive aggregation types are: AverageOfChildren FirstChild LastChild FirstNonEmpty LastNonEmpty They behave the same as measures with aggregation type Sum on all dimensions except Time dimensions. In order to get Analysis Services to recognize a Time dimension, you'll need to have set the dimension's Type property to Time in the Dimension Editor. Sometimes you'll have multiple, role-playing Time dimensions in a cube, and if you have semi-additive measures, they'll be semi-additive for just one of these Time dimensions. In this situation, Analysis Services 2008 RTM uses the first Time dimension in the cube that has a relationship with the measure group containing the semi-additive measure. You can control the order of dimensions in the cube by dragging and dropping them in the Dimensions pane in the bottom left-hand corner of the Cube Structure tab of the Cube Editor; the following blog entry describes how to do this in more detail: http://tinyurl.com/gregsemiadd. However, this behavior has changed between versions in the past and may change again in the future. Semi-additive aggregation is extremely useful when you have a fact table that contains snapshot data. For example, if you had a fact table containing information on the number of items in stock in a warehouse, then it would never make sense to aggregate these measures over time: if you had ten widgets in stock on January 1, eleven in stock on January 2, eight on January 3 and so on, the value you would want to display for the whole of January would never be the sum of the number of items in stock on each day in January. The value you do display depends on your organization's business rules. Let's take a look at what each of the semi-additive measure values actually do: AverageOfChildren displays the average of all the values at the lowest level of granularity on the Time dimension. So, for example, if Date was the lowest level of granularity, when looking at a Year value, then Analysis Services would display the average value for all days in the year. FirstChild displays the value of the first time period at the lowest level of granularity, for example, the first day of the year. LastChild displays the value of the last time period at the lowest level of granularity, for example, the last day of the year. FirstNonEmpty displays the value of the first time period at the lowest level of granularity that is not empty, for example the first day of the year that has a value. LastNonEmpty displays the value of the last time period at the lowest level of granularity that is not empty, for example the last day of the year that has a value. This is the most commonly used semi-additive type; a good example of its use would be where the measure group contains data about stock levels in a warehouse, so when you aggregated along the Time dimension what you'd want to see is the amount of stock you had at the end of the current time period. The following screenshot of an Excel pivot table illustrates how each of these semi-additive aggregation types works: Note that the semi-additive measures only have an effect above the lowest level of granularity on a Time dimension. For dates like July 17th in the screenshot above, where there is no data for the Sum measure, the LastNonEmpty measure still returns null and not the value of the last non-empty date.
Read more
  • 0
  • 0
  • 15076
Modal Close icon
Modal Close icon