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-categories-and-attributes-magento-part-2
Packt
22 Oct 2009
7 min read
Save for later

Categories and Attributes in Magento: Part 2

Packt
22 Oct 2009
7 min read
Time for action: Creating Attributes In this section we will create an Attribute set for our store. First, we will create Attributes. Then, we will create the set. Before you begin Because Attributes are the main tool for describing your Products, it is important to make the best use of them. Plan which Attributes you want to use. What aspects or characteristics of your Products will a customer want to search for? Make those Attributes. What aspects of your Products will a customer want to choose? Make these Attributes, too. Attributes are organized into Attribute Sets. Each set is a collection of Attributes. You should create different sets to describe the different types of Products that you want to sell. In our coffee store, we will create two Attribute Sets: one for Single Origin coffees and one for Blends. They will differ in only one way. For Single Origin coffees, we will have an Attribute showing the country or region where the coffee is grown. We will not have this Attribute for blends because the coffees used in a blend can come from all over the world. Our sets will look like the following: Single Origin Attribute set Blended Attribute set Name Name Description Description Image Image Grind Grind Roast Roast Origin SKU SKU Price Price Size Size   Now, let's create the Attributes and put them into sets. The result of the following directions will be several new Attributes and two new Attribute Sets: If you haven't already, log in to your site's backend, which we call the Administrative Panel: Select Catalog | Attributes | Manage Attributes. list of all the Attributes is displayed. These attributes have been created for you. Some of these Attributes (such as color, cost, and description) are visible to your customers. Other Attributes affect the display of a Product, but your customers will never see them. For example, custom_design can be used to specify the name of a custom layout, which will be applied to a Product's page. Your customers will never see the name of the custom layout. We will add our own attributes to this list. Click the Add New Attribute button. The New Product Attribute page displays: There are two tabs on this page: Properties and Manage Label / Options. You are in the Properties tab. The Attribute Properties section contains settings that only the Magento administrator (you) will see. These settings are values that you will use when working with the Attribute. The Frontend Properties section contains settings that affect how this Attribute will be presented to your shoppers. We will cover each setting on this page. Attribute Code is the name of the Attribute. Your customers will never see this value. You will use it when managing the Attribute. Refer back to the list of Attributes that appeared in Step 2. The Attribute identifier appears in the first column, labelled Attribute Code. The Attribute Code must contain only lowercase letters, numbers, and the underscore character. And, it must begin with a letter. The Scope of this Attribute can be set as Store View, Website, or Global. For now, you can leave it set to the default—Store View. The other values become useful when you use one Magento installation to create multiple stores or multiple web sites. That is beyond the scope of this quick-start guide. After you assign an Attribute set to a Product, you will fill in values for the Attributes. For example, suppose you assign a set that contains the attributes color, description, price, and image. You will then need to enter the color, description, price, and image for that Product. Notice that each of the Attributes in that set is a different kind of data. For color, you would probably want to use a drop-down list to make selecting the right color quick and easy. This would also avoid using different terms for the same color such as "Red" and "Magenta". For description, you would probably want to use a freeform text field. For price, you would probably want to use a field that accepts only numbers, and that requires you to use two decimal places. And for image, you would want a field that enables you to upload a picture. The field Catalog Input Type for Store Owner enables you to select the kind of data that this Attribute will hold: In our example we are creating an Attribute called roast. When we assign this value to a Product, we want to select a single value for this field from a list of choices. So, we will select Dropdown. If you select Dropdown or Multiple Select for this field, then under the Manage Label/Options tab, you will need to enter the list of choices (the list of values) for this field. If you select Yes for Unique Value, then no two products can have the same value for this Attribute. For example, if I made roast a unique Attribute, that means only one kind of coffee in my store could be a Light roast, only one kind of coffee could be a French roast, only one could be Espresso, and so on. For an Attribute such as roast, this wouldn't make much sense. However, if this Attribute was the SKU of the Product, then I might want to make it unique. That would prevent me from entering the same SKU number for two different Products. If you select Yes for Values Required, then you must select or enter a value for this Attribute. You will not be able to save a Product with this Attribute if you leave it blank. In the case of roast, it makes sense to require a value. Our customers would not buy a coffee without knowing what kind of roast the coffee has. Input Validation for Store Owner causes Magento to check the value entered for an Attribute, and confirm that it is the right kind of data. When entering a value for this Attribute, if you do not enter the kind of data selected, then Magento gives you a warning message. The Apply To field determines which Product Types can have this Attribute applied to them. Remember that the three Product Types in Magento are Simple, Grouped, and Configurable. Recall that in our coffee store, if a type of coffee comes in only one roast, then it would be a Simple Product. And, if the customer gets to choose the roast, it would be a Configurable Product. So we want to select at least Simple Product and Configurable Product for the Apply To field: But what about Grouped Product? We might sell several different types of coffee in one package, which would make it a Grouped Product. For example, we might sell a Grouped Product that consists of a pound of Hawaiian Kona and a pound of Jamaican Blue Mountain. We could call this group something like "Island Coffees". If we applied the Attribute roast to this Grouped Product, then both types of coffee would be required to have the same roast. However, if Kona is better with a lighter roast and Blue Mountain is better with a darker roast, then we don't want them to have the same roast. So in our coffee store, we will not apply the Attribute roast to Grouped Products. When we sell coffees in special groupings, we will select the roast for each coffee. You will need to decide which Product Types each Attribute can be applied to. If you are the store owner and the only one using your site, you will know which Attributes should be applied to which Products. So, you can safely choose All Product Types for this setting.
Read more
  • 0
  • 0
  • 3197

article-image-oracle-web-rowset-part1
Packt
22 Oct 2009
6 min read
Save for later

Oracle Web RowSet - Part1

Packt
22 Oct 2009
6 min read
The ResultSet interface requires a persistent connection with a database to invoke the insert, update, and delete row operations on the database table data. The RowSet interface extends the ResultSet interface and is a container for tabular data that may operate without being connected to the data source. Thus, the RowSet interface reduces the overhead of a persistent connection with the database. In J2SE 5.0, five new implementations of RowSet—JdbcRowSet, CachedRowSet, WebRowSet, FilteredRowSet, and JoinRowSet—were introduced. The WebRowSet interface extends the RowSet interface and is the XML document representation of a RowSet object. A WebRowSet object represents a set of fetched database table rows, which may be modified without being connected to the database. Support for Oracle Web RowSet is a new feature in Oracle Database 10g driver. Oracle Web RowSet precludes the requirement for a persistent connection with the database. A connection is required only for retrieving data from the database with a SELECT query and for updating data in the database after all the required row operations on the retrieved data has been performed. Oracle Web RowSet is used for queries and modifications on the data retrieved from the database. Oracle Web RowSet, as an XML document representation of a RowSet facilitates the transfer of data. In Oracle Database 10g and 11g JDBC drivers, Oracle Web RowSet is implemented in the oracle.jdbc.rowset package. The OracleWebRowSet class represents a Oracle Web RowSet. The data in the Web RowSet may be modified without connecting to the database. The database table may be updated with the OracleWebRowSet class after the modifications to the Web RowSet have been made. A database JDBC connection is required only for retrieving data from the database and for updating the database. An XML document representation of the data in a Web RowSet may be obtained for data exchange. In this article, the Web RowSet feature in Oracle 10g database JDBC driver is implemented in JDeveloper 10g. An example Web RowSet will be created from a database. The Web RowSet will be modified and stored in the database table. In this article, we will learn the following: Creating a Oracle Web RowSet object Adding a row to Oracle Web RowSet Modifying the database table with Web RowSet In the second half of the article, we will cover the following : Reading a row from Oracle Web RowSet Updating a row in Oracle Web RowSet Deleting a row from Oracle Web RowSet Updating Database Table with modified Oracle Web RowSet Setting the Environment We will use Oracle database to generate an updatable OracleWebRowSet object. Therefore, install Oracle database 10g including the sample schemas. Connect to the database with the OE schema: SQL> CONNECT OE/<password> Create an example database table, Catalog, with the following SQL script: CREATE TABLE OE.Catalog(Journal VARCHAR(25), Publisher Varchar(25),Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));INSERT INTO OE.Catalog VALUES('Oracle Magazine', 'OraclePublishing', 'July-August 2005', 'Tuning Undo Tablespace','Kimberly Floss');INSERT INTO OE.Catalog VALUES('Oracle Magazine', 'OraclePublishing', 'March-April 2005', 'Starting with Oracle ADF', 'SteveMuench'); Configure JDeveloper 10g for Web RowSet implementation. Create a project in JDeveloper. Select File | New | General | Application. In the Create Application window specify an Application Name and click on Next. In the Create Project window, specify a Project Name and click on Next. A project is added in the Applications Navigator. Next, we will set the project libraries. Select Tools | ProjectProperties and in the Project Properties window, select Libraries | Add Library to add a library. Add the Oracle JDBC library to project libraries. If the Oracle JDBC drivers version prior to the Oracle database 10g (R2) JDBC drivers version is used, create a library from the Oracle Web RowSet implementation classes JAR file: C:JDeveloper10.1.3jdbclibocrs12.jar. The ocrs12.jar is required only for JDBC drivers prior to Oracle database 10g (R2) JDBC drivers. In Oracle database 10g (R2) JDBC drivers OracleRowSet implementation classes are packaged in the ojdbc14.jar. In Oracle database 11g JDBC drivers Oracle RowSet implementation classes are packaged in ojdbc5.jar and ojdbc6.jar. In the Add Library window select the User node and click on New. In the Create Library window specify a Library Name, select the Class Path node and click on Add Entry. Add an entry for ocrs12.jar. As Web RowSet was introduced in J2SE 5.0, if J2SE 1.4 is being used we also need to add an entry for the RowSet implementations JAR file, rowset.jar. Download the JDBC RowSet Implementations 1.0.1 zip file, jdbc_rowset_tiger-1_0_1-mrel-ri.zip, from http://java.sun.com/products/jdbc/download.html#rowset1_0_1 and extract the JDBC RowSet zip file to a directory. Click on OK in the Create Library window. Click on OK in the Add Library window. A library for the Web RowSet application is added. Now configure an OC4J data source. Select Tools | Embedded OC4J Server Preferences. A data source may be configured globally or for the current workspace. If a global data source is created using Global | Data Sources, the data source is configured in the C:JDeveloper10.1.3jdevsystemoracle.j2ee.10.1.3.36.73embedded-oc4jconfig data-sources.xml file. If a data source is configured for the current workspace using Current Workspace | Data Sources, the data source is configured in the data-sources.xml file. For example, the data source file for the WebRowSetApp application is WebRowSetApp-data-sources.xml. In the Embedded OC4J Server Preferences window configure either a global data source or a data source in the current workspace. A global data source definition is available to all applications deployed in the OC4J server instance. A managed-data-source element is added to the data-sources.xml file. <managed-data-source name='OracleDataSource' connection-pool-name='Oracle Connection Pool' jndi-name='jdbc/OracleDataSource'/><connection-pool name='Oracle Connection Pool'><connection-factory factory-class='oracle.jdbc.pool.OracleDataSource' user='OE' password='pw'url="jdbc:oracle:thin:@localhost:1521:ORCL"></connection-factory></connection-pool> Add a JSP, GenerateWebRowSet.jsp, to the WebRowSet project. Select File | New | Web Tier | JSP | JSP. Click on OK. Select J2EE 1.3 or J2EE 1.4 in the Web Application window and click on Next. In the JSP File window specify a File Name and click on Next. Select the default settings in the Error Page Options page and click on Next. Select the default settings in the Tag Librarieswindow and click on Next. Select the default options in the HTML Options window and click on Next. Click on Finish in the Finish window. Next, configure the web.xml deployment descriptor to include a reference to the data source resource configured in the data-sources.xml file as shown in following listing: <resource-ref><res-ref-name>jdbc/OracleDataSource</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref>
Read more
  • 0
  • 0
  • 2372

article-image-fedora-8-more-linux-distribution
Packt
22 Oct 2009
4 min read
Save for later

Fedora 8 — More than a Linux Distribution

Packt
22 Oct 2009
4 min read
Fedora project leader, Max Spevack, has himself acknowledged this fact in his Fedora 8 pre-release announcement. "If you think back to the Fedora Core 6 release cycle, you will remember that a significant portion of the engineering goals for that release were driven by the knowledge that Fedora Core 6 would be the upstream for RedHat Enterprise Linux 5. Everyone knew going in that Fedora Core 6 would be more "corporate" than "community"," writes Spevack. Of course in a larger context this has worked for Fedora. The distro has gained much from its "closeness" to RHEL including its impressive security arsenal. As Spevack notes the community was "ok" with these diversions since "we also knew that once Red Hat Enterprise Linux 5 was released, the Fedora Project would be able to spend its next several releases focused on its community-related priorities." And what releases they have been! Fedora 7 marked a new direction for the distro. It merged both its in-house "core" and community "extra" repositories. This gave Fedora's community developers commit access to all Fedora packages, and along with a new build system, called Koji, completed Fedora's leap towards being a true community distro. Furthermore that release also introduced a new composing tool Pungi that produced installable distributions of Fedora once fed with a list of packages. Similarly the LiveCD Creator tool created Live CD and USB releases. Up to this point Fedora had been one of the few distros that didn't have a Live CD to show off itself. The graphical Revisor tool that lets users create installable and Live Fedora "spins" from a multitude of repositories is the cherry on the cake. Creating custom Fedora "spins" started with Fedora 7 and is also what Fedora 8 is all about. Well almost. In addition to an installable DVD, Fedora 8 has several installable Live spins including one each for GNOME and KDE desktops, a developer spin, a games spin, and an electronic lab spin. Since all the tools, from Pungi to Revisor, are free software and available in Fedora repositories, Fedora 8 is a perfect platform for creating your own installable Live CD. Creative Commons uses it for its Live CD to show off some of the quality content released under its license. What I haven't mentioned till now is that Fedora 8 itself is a fantastic release. Desktop users will enjoy its desktop wallpaper that changes color depending on the time of the day, the easy to use Firewall configuration tool and enhanced printer and network management in addition to the Compiz 3D desktop. I love the improved package management which makes adding software from the DVD and other online repositories, not only possible but a walk in the park. Fedora 8 also finds a solution for its inability to support patented media formats in the form of CodecBuddy. But like any other Linux distro Fedora 8 has its comfort zone, where everything works as it should. KDE under Fedora 8 doesn't fall in this category. I think openSUSE 10.3 sets the benchmark for maintaining consistency between GNOME and KDE desktop environments. In fact a few days before its release, Fedora's KDE Special Interest Group sent out a call for help, requesting participation citing a lack of active contributors. I am sure the community will respond and KDE's upcoming release, KDE 4 will be much stable under Fedora 9. Talking of Fedora 9, Spevack hints in Fedora 8's pre-release announcement that "Fedora 9 will probably start to see the pendulum swing back in the other direction [as opposed to Fedora 7 and 8's focus on the community], as Red Hat Enterprise Linux 6 starts to materialize on the horizon." I am not yet sure whether or not this is how things will turn out. But honestly though I think its time we stopped looking at Fedora as a distribution. While it's still early days, one look at Fedora 9's proposed feature list and you know what I'm talking about. Not only will the next release come out with more spins but if everything goes as planned it will expand the ability to create spins from other operating systems and even the web! For sure, Fedora has transitioned from just being a Linux distro to a platform for launching your own, and it's got the perfect recipe of tools to do so. You might also be interested in reading: GoboLinux: An Interview with Lucas Villa Real 2007 Open Source Content Management System Award
Read more
  • 0
  • 0
  • 5172

article-image-soap-and-php-5
Packt
22 Oct 2009
16 min read
Save for later

SOAP and PHP 5

Packt
22 Oct 2009
16 min read
SOAP SOAP, formerly known as Simple Object Access Protocol (until the acronym was dropped in version 1.2), came around shortly after XML-RPC was released. It was created by a group of developers with backing from Microsoft. Interestingly, the creator of XML-RPC, David Winer, was also one of the primary contributors to SOAP. Winer released XML-RPC before SOAP, when it became apparent to him that though SOAP was still a way away from being completed, there was an immediate need for some sort of web service protocol. Like XML-RPC, SOAP is an XML-based web service protocol. SOAP, however, satisfies a lot of the shortcomings of XML-RPC: namely the lack of user-defined data types, better character set support, and rudimentary security. It is quite simply, a more powerful and flexible protocol than REST or XML-RPC. Unfortunately, sacrifices come with that power. SOAP is a much more complex and rigid protocol. For example, even though SOAP can stand alone, it is much more useful when you use another XML-based standard, called Web Services Descriptor Language (WSDL), in conjunction with it. Therefore, in order to be proficient with SOAP, you should also be proficient with WSDL. The most-levied criticism of SOAP is that it is overly complex. Indeed, SOAP is not simple. It is long and verbose. You need to know how namespaces work in XML. SOAP can rely heavily on other standards. This is true for most implementations of SOAP, including Microsoft Live Search, which we will be looking at. The most common external specifications used by a SOAP-based service is WSDL to describe its available services, and that, in turn, usually relies on XML Schema Data (XSD) to describe its data types. In order to "know" SOAP, it would be extremely useful to have some knowledge of WSDL and XSD. This will allow one to figure out how to use the majority of SOAP services. We are going to take a "need to know" approach when looking at SOAP. Microsoft Live Search's SOAP API uses WSDL and XSD, so we will take a look at SOAP with the other two in mind. We will limit our discussion on how to gather information about the web service that you, as a web service consumer, would need and how to write SOAP requests using PHP 5 against it. Even though this article will just introduce you to the core necessities of SOAP, there is a lot of information and detail. SOAP is very meticulous and you have to keep track of a fair amount of things. Do not be discouraged, take notes if you have to, and be patient. All three, SOAP, WSD, and XSD are maintained by the W3C. All three specifications are available for your perusal. The official SOAP specification is located at http://www.w3.org/TR/soap/. WSDL specification is located at http://www.w3.org/TR/wsdl. Finally, the recommended XSD specification can be found at http://www.w3.org/XML/Schema. Web Services Descriptor Language (WSDL) With XML Schema Data (XSD) Out of all the drawbacks of XML-RPC and REST, there is one that is prominent. Both of these protocols rely heavily on good documentation by the service provider in order to use them. Lacking this, you really do not know what operations are available to you, what parameters you need to pass in order to use them, and what you should expect to get back. Even worse, an XML-RPC or REST service may be poorly or inaccurately documented and give you inaccurate or unexpected results. SOAP addresses this by relying on another XML standard called WSDL to set the rules on which web service methods are available, how parameters should be passed, and what data type might be returned. A service's WSDL document, basically, is an XML version of the documentation. If a SOAP-based service is bound to a WSDL document, and most of them are, requests and responses must adhere to the rules set in the WSDL document, otherwise a fault will occur. WSDL is an acronym for a technical language. When referring to a specific web service's WSDL document, people commonly refer to the document as "the WSDL" even though that is grammatically incorrect. Being XML-based, this allows clients to automatically discover everything about the functionality of the web service. Human-readable documentation is technically not required for a SOAP service that uses a WSDL document, though it is still highly recommended. Let's take a look at the structure of a WSDL document and how we can use it to figure out what is available to us in a SOAP-based web service. Out of all three specifications that we're going to look at in relationship to SOAP, WSDL is the most ethereal. Both supporters and detractors often call writing WSDL documents a black art. As we go through this, I will stress the main points and just briefly note other uses or exceptions. Basic WSDL Structure Beginning with a root definitions element, WSDL documents follow this basic structure:     <definitions>        <types>        …        </types>        <message>        …        </message>        <portType>        …        </portType>        <binding>        …        </binding>    </definitions> As you can see, in addition to the definitions element, there are four main sections to a WSDL document: types, message, portType, and binding. Let's take a look at these in further detail. Google used to provide a SOAP service for their web search engine. However, this service is now deprecated, and no new developer API keys are given out. This is unfortunate because the service was simple enough to learn SOAP quickly, but complex enough to get a thorough exposure to SOAP. Luckily, the service itself is still working and the WSDL is still available. As we go through WSDL elements, we will look at the Google SOAP Search WSDL and Microsoft Live Search API WSDL documents for examples. These are available at http://api.google.com/GoogleSearch.wsdl and http://soap.search.msn.com/webservices.asmx?wsdl respectively. definitions Element This is the root element of a WSDL document. If the WSDL relies on other specifications, their namespace declarations would be made here. Let's take a look at Google's WSDL's definition tag:     <definitions name="GoogleSearch"        targetNamespace="urn:GoogleSearch"                                                > The more common ones you'll run across are xsd for schema namespace, wsdl for the WSDL framework itself, and soap and soapenc for SOAP bindings. As these namespaces refer to W3C standards, you will run across them regardless of the web service implementation. Note that some searches use an equally common prefix, xs, for XML Schema. tns is another common namespace. It means "this namespace" and is a convention used to refer to the WSDL itself. types Element In a WSDL document, data types used by requests and responses need to be explicitly declared and defined. The textbook answer that you'll find is that the types element is where this is done. In theory, this is true. In practice, this is mostly true. The types element is used only for special data types. To achieve platform neutrality, WSDL defaults to, and most implementations use, XSD to describe its data types. In XSD, many basic data types are already included and do not need to be declared. Common Built-in XSD Data Types Time Date Boolean String Base64Binary Float Double Integer Byte For a complete list, see the recommendation on XSD data types at http://www.w3.org/TR/xmlschema-2/. If the web service utilizes nothing more than these built-in data types, there is no need to have special data types, and thus, types will be empty. So, the data types will just be referred to later, when we define the parameters. There are three occasions where data types would be defined here: If you want a special data type that is based on a built-in data type. Most commonly this is a built-in, whose value is restricted in some way. These are known as simple types. If the data type is an object, it is known as a complex type in XSD, and must be declared. An array, which can be described as a hybrid of the former two. Let's take a look at some examples of what we will encounter in the types element. Simple Type Sometimes, you need to restrict or refine a value of a built-in data type. For example, in a hospital's patient database, it would be ludicrous to have the length of a field called Age to be more than three digits. To add such a restriction in the SOAP world, you would have to define Age here in the types section as a new type. Simple types must be based on an existing built-in type. They cannot have children or properties like complex types. Generally, a simple type is defined with the simpleType element, the name as an attribute, followed by the restriction or definition. If the simple type is a restriction, the built-in data type that it is based on, is defined in the base attribute of the restriction element. For example, a restriction for an age can look like this:     <xsd:simpleType name="Age">        <xsd:restriction base="xsd:integer">            <xsd:totalDigits value="3" />        </xsd:restriction>    </xsd:simpleType> Children elements of restriction define what is acceptable for the value. totalDigits is used to restrict a value based on the character length. A table of common restrictions follows: Restriction Use Applicable In enumeration Specifies a list of acceptable values. All except boolean fractionDigits Defines the number of decimal places allowed. Integers length Defines the exact number of characters allowed. Strings and all binaries maxExclusive/ maxInclusive Defines the maximum value allowed. If Exclusive is used, value cannot be equal to the definition. If Inclusive, can be equal to, but not greater than, this definition. All numeric and dates minLength/ maxLength Defines the minimum and maximum number of characters or list items allowed. Strings and all binaries minExclusive/ minInclusive Defines the minimum value allowed. If Exclusive is used, value cannot be equal to the definition. If Inclusive, can be equal to, but not less than, this definition. All numeric and dates pattern A regular expression defining the allowed values. All totalDigits Defines the maximum number of digits allowed. Integers whiteSpace Defines how tabs, spaces, and line breaks are handled. Can be preserve (no changes), replace (tabs and line breaks are converted to spaces) or collapse (multiple spaces, tabs, and line breaks are converted to one space. Strings and all binaries A practical example of a restriction can be found in the MSN Search Web Service WSDL. Look at the section that defines SafeSearchOptions.     <xsd:simpleType name="SafeSearchOptions">        <xsd:restriction base="xsd:string">            <xsd:enumeration value="Moderate" />            <xsd:enumeration value="Strict" />            <xsd:enumeration value="Off" />    </xsd:restriction> </xsd:simpleType> In this example, the SafeSearchOptions data type is based on a string data type. Unlike a regular string, however, the value that SafeSearchOptions takes is restricted by the restriction element. In this case, the several enumeration elements that follow. SafeSearchOptions can only be what is given in this enumeration list. That is, SafeSearchOptions can only have a value of "Moderate", "Strict", or "Off". Restrictions are not the only reason to use a simple type. There can also be two other elements in place of restrictions. The first is a list. If an element is a list, it means that the value passed to it is a list of space-separated values. A list is defined with the list element followed by an attribute named itemType, which defines the allowed data type. For example, this example specifies an attribute named listOfValues, which comprises all integers.     <xsd:simpleType name="listOfValues">        <xsd:list itemType="xsd:integer" />    </xsd:simpleType> The second is a union. Unions are basically a combination of two or more restrictions. This gives you a greater ability to fine-tune the allowed value. Back to our age example, if our service was for a hospital's pediatrics ward that admits only those under 18 years old, we can restrict the value with a union.     <xsd:simpleType name="Age">        <xsd:union>            <xsd:simpleType>                <xsd:restriction base="decimal">                        <xsd:minInclusive value="0" />                </xsd:restriction>            </xsd:simpleType>            <xsd:simpleType>                <xsd:restriction base="decimal">                        <xsd:maxExclusive value="18" />                </xsd:restriction>            </xsd:simpleType>        </xsd:union>    </xsd:simpleType> Finally, it is important to note that while simple types are, especially in the case of WSDLs, used mainly in the definition of elements, they can be used anywhere that requires the definition of a number. For example, you may sometimes see an attribute being defined and a simple type structure being used to restrict the value. Complex Type Generically, a complex type is anything that can have multiple elements or attributes. This is opposed to a simple type, which can have only one element. A complex type is represented by the element complexType in the WSDL. The most common use for complex types is as a carrier for objects in SOAP transactions. In other words, to pass an object to a SOAP service, it needs to be serialized into an XSD complex type in the message. The purpose of a complexType element is to explicitly define what other data types make up the complex type. Let's take a look at a piece of Google's WSDL for an example:     <xsd:complexType name="ResultElement">        <xsd:all>            <xsd:element name="summary" type="xsd:string"/>            <xsd:element name="URL" type="xsd:string"/>            <xsd:element name="snippet" type="xsd:string"/>            <xsd:element name="title" type="xsd:string"/>            <xsd:element name="cachedSize" type="xsd:string"/>            <xsd:element name=                        "relatedInformationPresent" type="xsd:boolean"/>            <xsd:element name="hostName" type="xsd:string"/>            <xsd:element name=                        "directoryCategory" type="typens:DirectoryCategory"/>            <xsd:element name="directoryTitle" type="xsd:string"/>        </xsd:all>    </xsd:complexType> First thing to notice is how the xsd: namespace is used throughout types. This denotes that these elements and attributes are part of the XSD specification. In this example, a data type called ResultElement is defined. We don't exactly know what it is used for right now, but we know that it exists. An element tag denotes complex type's equivalent to an object property. The first property of it is summary, and the type attribute tells us that it is a string, as are most properties of ResultElement. One exception is relatedInformationPresent, which is a Boolean. Another exception is directoryCategory. This has a data type of DirectoryCategory. The namespace used in the type attribute is typens. This tells us that it is not an XSD data type. To find out what it is, we'll have to look for the namespace declaration that declared typens.
Read more
  • 0
  • 0
  • 5329

article-image-filtering-microsoft-dynamics-nav
Packt
22 Oct 2009
3 min read
Save for later

Filtering in Microsoft® Dynamics™ NAV

Packt
22 Oct 2009
3 min read
Filtering As mentioned earlier, filtering is one of the very powerful tools within NAV C/AL. Filtering is the application of defined limits on the data to be considered in a process (to learn more about Data types in NAV, visit here). Filter structures can be applied in at least three different ways, depending on the design of the process. The first way is for the developer to fully define the filter structure and the value of the filter. This might be done in a report designed to show only information on a selected group of customers, for example those with an open Balance on Account. The Customer table would be filtered to report only customers who have an Outstanding Balance greater than zero. The second way is for the developer to define the filter structure, but allow the user to fill in the specific value to be applied. This approach would be appropriate in an accounting report that was to be tied to specific accounting periods. The user would be allowed to define what period(s) were to be considered for each report run. The third way is the ad hoc definition of a filter structure and value by the user. This approach is often used for general analysis of ledger data where the developer wants to give the user total flexibility in how they slice and dice the available data. It is quite common within the standard NAV applications and in the course of enhancements to use a combination of the different filtering types. For example, the report just mentioned that lists only customers with an open Balance on Account (via a developer-defined filter) could also allow the user to define additional filter criteria. Perhaps, the user wants to see only Euro currency-based customers, so they would filter on the Customer Currency Code field. Filters are an integral part of FlowFields and FlowFilters, two of the three Field Classes. These are very flexible and powerful tools, which allow the NAV designer to create forms, reports, and other processes that can be used by the user under a wide variety of circumstances for various purposes. In most systems, user inquiries (forms and reports) and processes need to be quite specific to different data types and ranges. The NAV C/AL toolset allows you to create relatively generic user inquiries and processes and then allow the user to apply filtering to fit their specific needs. Defining Filter Syntax and Values Let us go over some common ways in which we can define filter values and syntax. Remember, when you apply a filter, you will only view or process records where the filtered data field satisfies the limits defined by the filter. Equality and inequalityeither an equal (=) sign or no sign filters for data "equal to" the filter value. Data Type - description Example Filters Integer =200 Integer 200 Text Chicago Text " (two single quote marks)         a greater than (>) sign filters for data greater than the filter value Data Type - description Example Filters Integer >200 Date >10/06/07 Decimal >450.50         a less than (<) sign filters for data less than the filter value Data Type - description Example Filters Integer <150 Date <10/07/07
Read more
  • 0
  • 0
  • 3091

article-image-joomla-installation-virtual-server-net
Packt
22 Oct 2009
3 min read
Save for later

Joomla! Installation on a Virtual Server on the Net

Packt
22 Oct 2009
3 min read
In principle the simplest approach that actually always works is the following: Load the Joomla! 1.5 beta.zip file onto your local PC and unpack it in a temporary directory. Load the just unpacked files by means of FTP onto your rented server. The files must be installed in the publicly accessible directory. These directories are usually named htdocs, public_html, or simply html. You can specify a subdirectory within the directory into which you install your Joomla!. Many web hosts allow you to link your rented domain name to a directory. This name is necessary to call your website from a browser. You have to find out what your database is called. Usually one or several databases are included in your web-hosting package. Sometimes the user name, database name, and password are fixed; sometimes you have to set them up. There is usually a browser-based configuration interface at your disposal. You can see an example of such an interface in the following figure. You will need these access data for Joomla!'s web installer. You can get going after you have loaded these data onto your server and are in possession of your access data. Joomla! Installation To install Joomla!, you need the source code. Download the Joomla_1.5.0-Beta-Full_Package.zip package and save it on your system. Selecting a Directory for Installation You have to decide whether Joomla! needs to be installed directly into a document directory or a subdirectory. This is important, since many users prefer a short URL to their homepage. An Example If Joomla! is unzipped directly in /htdocs, the web page starts when the domain name http://www.myhomepage.com is accessed from its local computer http://localhost/ and/or from the server on the Internet. If subdirectories are created under /htdocs/, for example, /htdocs/Joomla150/ and we unzip the package there, we have to enter http://localhost/Joomla150/ in the browser. This isn't a problem locally, but doesn't look good on a production Internet page. Some HTML files and subdirectories, however, are already in /htdocs in the local XAMPP Lite environment under Windows, which, for example, displays the start page of XAMPP Lite. In a local Linux environment, a starting page dependent on the distribution and the web server settings is also displayed. Directory I recommend that you create a subdirectory under the document directory named Joomla150 in Windows by using Windows Explorer. (With Linux, use the Shell, KDE Konqueror, or Midnight Commander.) [home]/htdocs/Joomla150/ The directory tree in Windows Explorer should look like this: An empty index appears in the XAMPP Lite version when the URL http://localhost/Joomla150 is entered in the browser: With Linux or with another configuration it can happen that you get a message saying that you don't have access to this directory. This depends on the configuration of the web server. For security reasons, the automatic directory display is often deactivated in Apache's configuration. A potential hacker could draw many interesting conclusions about the directory structure and the files on your homepage and target your computer for an attack. For security reasons, you are usually not allowed to access the appropriate configuration file of the Apache web server. Should you be able to, you should leave the content directories deactivated and/or only activated for those directories that contain files for downloading.        
Read more
  • 0
  • 0
  • 1685
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-visual-sourcesafecreating-service-oriented-application
Packt
22 Oct 2009
17 min read
Save for later

Visual SourceSafe:Creating a Service-Oriented Application

Packt
22 Oct 2009
17 min read
I will build a prototype for a hotel reservation system outlining the way Software Configuration Management makes the job easier. Don't worry if you are not fully familiar with the technologies used. The purpose of this application is purely for reference, so you can sit back and relax. At this point I will use my time machine and get a screenshot for the final application so you can see how it will look like. Or, I can insert the screenshot after it finished. I think the first way seems more reasonable. This is what the public reservation site looks like: If you like it, you can download the application from the book's website: http://orbitalhotel.alexandruserban.com. Now let's get back to our time and start the development lifecycle on the Orbital Hotel product. The first phase is the specifications phase. Specifications—Project Architecture In order to build a software system, we need a list of requirements. What is the purpose of the system? What are the actions performed by the system and against the system? Who will use the system and how? The answers to these questions will let us identify the main parts of the system and the way these parts work together. System Requirements Let's take a look at the Orbital Hotel's reservation system's requirements. The purpose of the reservation system is to allow guests to make room reservations. There are several room types each having a number, occupancy, price, availability, description, and image. The reservations can be made by using the hotel's internet website, through the websites of travel agencies (third parties), or by making phone calls to the hotel's client service. Reservations can be also made by internal client service staff who receive phone calls from guests. When guests use the hotel's website, they will create a user with a username and password and input their personal details such as first name, last name, address, city, zip code, state, country, phone, email address, and card number. Then they will choose a room and complete the reservation details such as arrival date, the number of nights they will be staying and the number of adults, teenagers, children, and pets. They will also be able to cancel their reservation. When making a reservation over the phone, a guest will provide the same personal information and reservation details to the hotel's client-service staff. The staff will create a reservation for the guest using an internal application. The staff members will also authenticate using a username and password. Travel agencies and other third parties must also be able to make hotel reservations. Taking a big picture about the type of system we are going to build, what we need is an application design that will be as flexible as possible. It should provide us with a variety of options like reservations through phone calls, personal or third-party websites, smart devices like PDAs or cell phones, and so on. This is where we gather the specifications and plan the system architecture. In this phase we have to consider as many aspects as we can, based on our requirements and specifications. So, let's see what the main existing application architectures are, and see what application architecture fits our requirements. Application Architectures The computer and computer programming history is a very short one in comparison with that of other industries. Although it is short, it has evolved and continues to evolve very rapidly, changing the way we live. Taking into account the architectures used at the beginning of computer programming, we can see an evolution from the single, powerful, fault-tolerant, expensive super mainframe computer applications, towards multiple, distributed, less expensive smaller machine applications, the personal computers. During this evolution, three main application architectures can be identified: Compact application architecture Component application architecture Service-Oriented Architecture (SOA) We are going to take a brief look at these application architectures and outline their characteristics. Compact Application Architecture During application development for the single mainframe, there was no clear separation between application layers and no reusable components were used. All the data access, business logic, and user interface-specific code were contained in a single executable program. This traditional compact architecture was used because the mainframe computers had specific proprietary programming languages and formats for accessing and manipulating the data. All the data access-specific procedures as well as the business logic and business rules code are written in this programming language. At the surface, a user interface is presented to the user for data visualisation and manipulation. This application architecture works for applications that do not need data input from multiple sources and can be easily developed by a single programmer. However, this approach has several major disadvantages when it comes to building large-scale systems: Application components cannot be reused in other applications because they are tightly coupled and dependent on one another. Tight coupling means that in order for a piece of code to use another piece of code, it must have intimate knowledge about its implementation details. Being tightly coupled, a change to one component can affect the functionality of another, making debugging and maintenance a difficult task. The application is actually a black box; no one, except the main developer, knows what it is in there. Applying security is another problem because the user interface cannot be separated from the business logic components using security-specific mechanisms like authentication and authorization. Application integration is affected because the code is platform dependent. Integration between two such applications requires special and specific coding and can be difficult to maintain. Scalability issues are considered when the system grows and need to be scaled across several machines. Using this application architecture, scalability is not possible as you can't separate different application parts across different physical boundaries because of the tight coupling. To address the issues with the compact application architecture, the component-based application architecture was developed. Component Application Architecture In the component application architecture, the application's functionality is defined using components. A component is like a black box, a software unit that encapsulates data and code and provides at the surface a set of well-defined interfaces used by other components. Since a component only needs to support a well-defined set of interfaces, it can change the inner implementation details without affecting other components that use its external interfaces. Components that export the same interfaces can be interchanged, allowing them to be reused and tight coupling to be eliminated. This makes them loosely coupled because they don't need to know internal implementation details of one another. This separation of application functionality using components allows the distribution of development tasks across several developers and makes the overall application more maintainable and scaleable. In the Windows environment, the most used component application architecture is the Component Object Model (COM). Typically, components are grouped into logical layers. For example, an application uses the data access layer to access the different data sources, the business logic layer to process the data according to the business rules, and the presentation layer also known as the user interface layer to present the data to end users. Using well-defined application layers allows for a modular design, component decoupling, and therefore the possibility for component reuse. Data Access Layer This architecture forms a chain of layers that communicate with one another. The base is the data access layer, which is responsible for querying, retrieving, and updating the data from and to different data sources while providing a uniform data view to the layers above. Business Layer Above the data access layer is the business logic layer. The business logic layer uses the uniform data provided by the data access layer and processes it according to the business rules it contains. The business logic layer doesn't need to know from what source and how the data was obtained. Its purpose is only data manipulation and processing. Presentation Layer At the top of the chain is the presentation layer or the user interface layer. Its purpose is to present the data processed by the business logic layer to end users and to receive input and commands from these end users. The presentation layer will propagate these commands down the chain to the business layer for processing. Characteristics The component application architecture solves many software problems and it has been used extensively in the past. But because software evolves continuously, new requirements introduce new challenges. Let's suppose we have several applications on different platforms, each incorporating its presentation layer, business logic layer, and data access layer. We want to integrate them into a bigger distributed system, a system that spans across several heterogeneous environments. At some point, one application will need to access the data existing in another application. While components can work well in a homogenous environment on the same platform, for example COM in the Windows environment, problems appear in components working across several platforms. For example, it is very difficult for a COM component to be used from a Java application or vice-versa, mainly because they don't speak the same language. Integration between two or more applications running on different platforms would require a middle component-dependent intercommunication layer that is expensive, difficult to build, and reintroduces tight coupling between systems, which is what we tried to avoid in the first place. Avoiding building this intercommunication layer would require that the data exchange between these applications be done by a person who will read the necessary data from the source application and write it into the target application. We need to integrate these systems, and maintain the loose coupling between them. What we need to do, is make these components understand each other, making them to speak the same language. This is where the concept of services and Service-Oriented Architecture (SOA) comes into play. Service-Oriented Architecture SOA describes an information technology architecture that enables distributed computing environments with many different types of computing platforms and applications. To enable distributed computing environments, SOA defines the concept of services. A service is a well-defined, self-contained unit of functionality, independent of the state of other services. Let's see how services can be used to create distributed applications, integrate component-based applications, and make them communicate with each other. We keep our data access layer and business logic layer as they are, but we completely decouple the presentation layer so we can change it later without affecting the other layers. In order to expose the functionality of the business logic layer, we wrap it in a service interface. The service interface wraps the business logic layer components offering a point of access for any process that needs to access the business logic, whose functionality has now become a service. Service-oriented architecture is basically a collection of services that communicate with each other. The communication can involve either simple data passing or it can involve two or more services coordinating some activity. Whatever the required functionality may be, we have now separated the functionality of applications into specific units, the services that we use to construct flexible, distributed applications. Typically services reside on different machines. They are exposed to the outside world by service interfaces. A service provider provides its functionality using the service interfaces that are used or consumed by the service consumers. A service consumer sends a service request to a service interface and receives a service response. The following figure represents a typical service consumer-service provider request. A service can be a service provider and a service consumer at the same time as it can consume other services. They communicate using a communication medium like a local area network for internal services or the Internet for external services. This communication medium is called a service bus. We saw that services don't have a presentation layer as we've decoupled the presentation layer from the rest. This presents an advantage because we can now use any platform able to understand and consume the service to build a presentation layer. The service interface has to provide a standard and open way of communication, a common language that both service providers and service consumers can understand, regardless of the machine type they are deployed on, their physical location, and the language in which they are written. XML Web Services In today's world, the communication standard used to connect services is achieved using web services. Web services are small, reusable applications that help computers with many different operating system platforms work together by exchanging messages. Web services are based on industry protocols that include XML (Extensible Markup Language), SOAP (Simple Object Access Protocol), and WSDL (Web Services Description Language). These protocols help computers work together across platforms and programming languages enabling data exchange between otherwise unconnected sources: Client-to-Client: Devices, also called smart clients, can host and consume XML web services, allowing data sharing anywhere, anytime. Client-to-Server: A server application can share data with desktop or mobile devices using XML web services over the Internet. Server-to-Server: Independent server applications can use XML web services as a common interface to share and exchange data. Service-to-Service: Systems that work together to deliver complex data processing can be created using XML web services. The following figure shows an example of services exposed using web services, which deliver their functionality to a wide variety of platforms and applications. Service-oriented architecture provides us with the maximum flexibility in building applications. Individual services define specific application functions and interact with one another to provide the entire business process functionality. Encapsulation: Just as an object encapsulates its internal implementation details inside while providing public methods to external objects, services encapsulate their internal complexity and implementation from the service consumers who don't have to know the internal details. Mobility: As services are independent and encapsulated, they can be deployed in any location. Since they are using the same standard communication language, they are accessed in the same way irrespective of their physical location or implementation details. Parallel development: A service-oriented application is built using several service layers and clients. These application components can be built in parallel by developers specialized in specific layer functionality, speeding up the development process. Platform independence: Service providers and service consumers can be written in any language and deployed on any platform, as long as they can speak the standard communication language. Security: More security can be added to a service-oriented application at the service interface layer. Different application components require different security levels. The security can be enforced by using firewalls configured to allow access only to the required service providers only by the required service consumers. In addition, by using Web Service Enhancements (WSE), authentication, authorization, and encryption can be easily added. Reusability: Once a service is constructed and deployed, it can be used by any other service consumer without problems related to platform integration and interoperability. Choosing an Application Architecture Now that we have seen the existing application architectures, we must choose one that meets our project requirements. As you may have guessed by this point, the best application architecture we can use for our project is a Service-Oriented Architecture (SOA). The SOA allows us to build a distributed system, a system that has great flexibility and interoperability with other systems on other platforms. This will allow us to build the business logic functions and expose them as services that will be used by higher functionality layers. Choosing an Application Platform After choosing our application architecture, we must choose a platform capable of building and supporting it. For the purpose of our system we will choose the Microsoft .NET Framework platform and build the system using Microsoft Visual Studio.NET 2005 and Microsoft SQL Server as the back-end database for storing the data. Microsoft .NET Framework From a Service-Oriented Architecture point of view, the .NET Framework is the Microsoft strategy for connecting systems, information, and devices through software such as web services. .NET technology provides the capability to quickly build, deploy, manage, and use connected, security-enhanced solutions through the use of web services. Intrinsically, the .NET Framework is an environment for development and execution that allows different programming languages and libraries to work together to create Windows-based applications that are easier to build, manage, deploy, and integrate with other networked systems. The .NET core components are: The Common Language Runtime (CLR): A language-neutral development and execution environment that provides a consistent model and services to manage application execution that includes: Support for different programming languages: A variety of over 20 programming languages that target the CLR, such as C#, VB.NET, and J#, can be used to develop applications. Support for libraries developed in different languages: Libraries developed in different languages integrate seamlessly, making application development faster and easier. Support for different platforms: .NET applications are not tied to a single platform and can be executed on any platform that supports the CLR. Enhanced security: The .NET Code Access Security model provides a managed environment for application execution and security. Automatic resource management: The CLR automatically handles process, memory, and thread management, enabling developers to focus on the core business logic code.   The Framework Class Libraries (FCL): An object-oriented library of classes that extends a wide range of functionality including: Support for basic operations: Input/output and string management, standard network protocols, and network standards such as TCP/IP, XML, SOAP, and HTTP are supported natively to allow basic operations and system connections. Support for data access and data manipulation: The FCL includes a range of data access and data manipulation classes forming the ADO.NET technology that natively supports XML and data environments such as SQL Server and Oracle. Support for desktop applications: Rich desktop and mobile client applications can be easily created using the Windows Forms technology. Support for web applications: Thin web clients, websites, and web services can be created using web forms and XML web services technologies that form ASP.NET.   In the planning phase we've gathered the project requirements and specifications and we've also chosen an application architecture. The next phase is the design phase. Designing the System In the design phase, we will create an application design based on the application architecture, project requirements, and specifications. Gathering all the information needed to design the system is a difficult task, but the most important step is to start writing down the first idea. System Structure The system will be composed from the following main component categories: Core components (Data Access Layer, Business Logic Layer) forming the middle-tier component layers. Web service components (XML Web service) forming the Service Interface layer. Website components (ASP.NET website) forming the front-end WebReservation application, a web presentation layer. Windows Application components (Windows Forms Application) forming the WinReservation application, a Windows presentation layer. The following figure illustrates the overall system structure, outlining each system component: As we saw earlier, one major advantage of a service-oriented application is the decoupling of the presentation layer from the business logic layer. This allows for the business logic layer being exposed as a web service to be used by other third parties to integrate its functionality into their business process. Database Structure The back-end database is hosted by a Microsoft SQL Server system. According to the project specifications the internal database structure will be composed of the following database tables: User (Contains the user accounts) Guest (Contains the personal details of the guests) Room (Contains the details of each of the hotel's rooms) Reservation (Contains the details of the reservation made by each user) The following figure illustrates these tables and the relations between them. The bold fields are mandatory (not NULL). The User table contains the following rows:    
Read more
  • 0
  • 0
  • 4652

article-image-modeling-furniture-blender
Packt
22 Oct 2009
10 min read
Save for later

Modeling Furniture in Blender

Packt
22 Oct 2009
10 min read
Create Models or Use a Library? There are two possibilities when working with furniture. We can create new furniture, or use pre-made models from a library. The question is: when must we use each type? Some people say that using a pre-made model is not very professional thing but what they forget to say is that most projects have a tight deadline, and we need a quick modeling process to be ready on time. So, what's most important for professionals? Getting things done, or telling the client that all the models were created just for his project? Of course, the deadline is the most important, and your clients normally won't mind if you use pre-made models. Probably they won't even notice. So don't be ashamed to use pre-made models they won't make your projects any less professional. It's even recommended to use these models to speed-up the process, and allow you to spend more time on lighting or texturing. Is there any situation that demands the creation of a furniture model from scratch? Well, there are some. First, if you can't find the model in any library that you know, then it's going to be necessary to create it from scratch. If you are working with an architect who designs the spaces and furniture as well, you will probably have to model the furniture too, since it won't be available at any public library. Any project that deals with customized furniture will require that we work on the modeling for the furniture. Create your own libraryA good practice for anyone doing architectural visualization is to collect a lot of 3D models from public libraries for use in future projects. Keep these models for later, but don't forget to check if the author has released the models with no restrictions for commercial use. Otherwise, you must get their permission to use them. If you want to create your library, with no restrictions, why not create your own models? This could be a good exercise: take a few examples, and start creating some furniture. With time, you will have a good number of models. How to Get Started? In most cases, we have to get used to all that furniture modeling. We will have to start from scratch, with no blueprints available. The only references that we will have would be the photos, either provided by our clients, or provided from some web resources. If you have the time, visit a real store, and take some pictures and measures on your own. Sometimes, these stores will give you fliers and brochures, especially if you work with architecture. With time, you will get a lot of good reference material, and some of them come with measurements. But, if you don't know where to get started, let me point out some great web resources: http://www.e-interiors.net http://resources.blogoscopia.com http://blender-archi.tuxfamily.org/Models http://www.katorlegaz.com/ http://sketchup.google.com/3dwarehouse The first link has a lot of reference images classified by furniture type and designer. And sometimes, they even provide free 3D models. Most models there are saved in DXF, or 3DS file formats. Appending Models Before we start to model, let's see how we can import a model form an external library into Blender. The process is very simple, and what we have to do is to use the File menu, and access the Append or Link option. There is a shortcut for that too - just press SHIFT+F1 to call the same function. With this option, we have to select file that is already in the Blender file format. This option won't import files in other formats. When we select a file, a list of elements available in that particular file will be displayed, for us to select what we want to import. In most cases, the models will be stored under Object. When we click the Object option, all of the objects available in the file will be listed. If you know the name of the object that you want to import, just select the name, and click Load Library. The object will be loaded into our scene. Here, we have two options to handle this object: Append or Link: Append: If we choose this option, the object will be merged into ourcurrent scene. Link: With this option, an external link to the object file will be created. Any modifications to the original file will be reflected in our current scene. What is the best method to use? It will depend on whether we are willing to track all modifications applied to our furniture models. Using the Link method is a great way of keeping the furniture updated, because every modification at the original file is reflected immediately in the scene in which this model is placed. However, we will have to take the original file with the scene file every time we need to put our scene on another computer. They always have to go together. But if you choose to use the Append option, things will be a bit simpler, because the object will be incorporated into the scene file. We won't have to be worried about moving the furniture file along with the scene. Always use the Append option when you want to use furniture, or any other model, saved in another Blender file. To use a furniture model saved in another file, with a type other than “.blend”, we have to use the Import option. Importing Models To import a model, the process is very simple. We must use the File menu and select, Import. Then we have to select the proper file type from the list. The best file type, and the most common for furniture blocks, is the 3Ds file format, which belongs to the old 3D Studio application. There are some other good formats that work well with Blender, such as OBJ and LWO. The 3Ds file format can store lights, and it works well with Blender. The only thing we have to take extra care about is that most models imported come with triangular faces, which are a bit harder to edit. But, if you don't need to make any modifications to the model, this won't be a problem. Append or Import?Just to make things clearer, if you download a furniture model from a web site, and it's saved in the Blender native file format (.blend), you should append the model. If you download or get a furniture model on any file format other than “.blend”, you will have to import it. Since most models aren't saved in the Blender native file format, we can safely say that almost all furniture models that you find will require an import action to be placed in your scenes. Modeling a Chair Let's start with something simple, such as a chair. Even for a simple model, it will help us deal with smaller dimensions and details. Here is an image of the model: What's the main objective of this modeling? We have to create this chair, with the minimum use of faces and vertices. A good amount of detail can be left for textures, and it's always a good choice to use a lower number of vertices and faces in a model. If you consider one model, it won't matter much. But with a large number of chairs, such as in a theater room, it can make a difference in render time. Let's get started with a simple cube. Select this cube, and change the work mode to Edit. Select all vertices and press the W key. This will open the Specials menu. Choose subdivide, just once, from this menu. This will create new vertices and edges. Once these new vertices have been created, as shown in the image to the left, below, press the A key to remove all of the objects from the selection. Now, select the vertices to the right, using the B key. Remember to change the view mode to Wireframe before using the B key, otherwise, we won't be able to select the vertices behind the visible faces. When these vertices are selected, press the X key and choose Vertices to erase only the selected vertices. Using the CTRL+R key, add a new edge loop to the model, as shown in the following image: The next step is to change the scale of our model. Rotate the view to see the model in perspective view. Select all objects and press the S key, immediately after pressing the Z key. This will make the scale work only in the Z axis. Now, select the vertices identified in the following image and erase them using the X key. Change the selection mode to Edges, and select the edges identified in the following image. With the edges selected, press the E key to extrude them. With the new faces created, we can now add some detail to the model. Select only the top edge of the previously created faces. Move this edge down just a bit. This will add a small declivity to the seat. Now, we can move on to the next extrude, which must be from the selected edges identified in the following image. I'm not using any kind of measure for this example, but if you like to work only with real measurements, remember to hold the CTRL key every time a new extrude or edge is moved. This way, all transformations will use the grid lines. For this model, I'm not using vertex snap. With the new faces created, select just the two edges identified in the following image. Extrude these edges until they reach the other side of the base model. Hold the CTRL key, while you extrude them, to help with the precision. If you already want to remove duplicated vertices, select all objects, and press the W key. Choose Remove doubles to erase any duplicated vertices. Select the edges identified in the image to keep adding more parts to the chair. Extrude the edges three times until you have the same structure showed here. Now, we have to close the top with a face. To do that, we must select all four vertices on the top. When the vertices are selected, press the F key to create a new face. The next step is to select the small side edges to create some detail. Select just one edge, beginning from bottom to top, and move it just a bit. Repeat this operation with the other edges until we get the edges positioned as in the following image. The basic shape of our chair has now been created. Now, we can make some adjustments for improving the overall proportions. Select all edges or vertices on the left side, and move them a bit to the left. This will make the model wider. Did you notice that we have modeled only half a chair? Now we can make the other half, using the Mirror modifier. Add the modifier, and choose the right axis to make a perfect copy. If the center point for the model has been moved, you might need to edit the model to create a perfect mirrored match. Don't worry if you have moved the model by accident - this can happen sometimes. Along with the Mirror modifier, add a Subsurf modifier, too. With the Subsurf modifier, we realize that this model needs a new edge loop on the left side. Just press CTRL+R, and add a new loop, as in the following image.
Read more
  • 0
  • 0
  • 9612

article-image-debugging-ajax-using-microsoft-ajax-library-internet-explorer-and-mozilla-firefox
Packt
22 Oct 2009
8 min read
Save for later

Debugging AJAX using Microsoft AJAX Library, Internet Explorer and Mozilla Firefox

Packt
22 Oct 2009
8 min read
AJAX Debugging Overview Unfortunately, today’s tools for client-side debugging and tracing aren’t as evolved as their server-side counterparts. For example, things such as capturing ongoing communication traffic between the client and the server, or client-side debugging, aren’t usually supported by today’s IDEs (Integrated Development Environments) such as Microsoft Visual Studio 2005. The next version of Visual Studio (code-named Orcas at the time of writing) promises a lot of improvements in this area: Improved IntelliSense technology with support for JavaScript code, which provides coding hints based on specially-formatted comments in the code Breakpoints in inline JavaScript code These are only the most important new coming features; there are others as well. For more information we suggest that you browse and keep an eye on Scott Guthrie’s blog at http://weblogs.asp.net/scottgu/, the JScript blog at http://blogs.msdn.com/jscript/, Bertrand Le Roy’s blog at http://weblogs.asp.net/bleroy/. Until this new edition of Visual Studio is released, we can rely on third-party tools that can do a very good job at helping us develop our AJAX applications. You’ll find a number of tools for Internet Explorer and Mozilla Firefox for this purpose. Debugging and Tracing with Microsoft AJAX Library The common practices for debugging JavaScript code are: Putting alert messages throughout the code to get notified about the values of the variables Logging tracing messages in a <div> element While the first option is straightforward, the second option offers a centralized place for storing different messages and could be considered more appropriate. Nevertheless both options can come in quite handy depending on the circumstances. Microsoft AJAX Library offers the Sys.Debug object that has a series of methods that you can use for debugging and tracing. The diagram of this class is presented in figure below. The Debug class As we can easily see in the diagram, Sys.Debug offers the most common features that we can find also in other languages: assert(), trace(), traceDump(), fail(), and clearTrace(). assert(), trace(), and fail() automatically send the messages to the debugging console of the browser. To see the messages in IE you need to have the Web Development Helper, and for Firefox you need the Firebug plugin. Both of these tools are presented later in this article. Internally assert() calls fail() if the expression evaluates to false. fail() simply logs the message passed in by assert to the debugging console. trace() offers an interesting feature beside logging to the debugging console: it offers the possibility to log the trace message in a <textarea> element with the ID TraceConsole. If such an element is found, trace() will log this message in this element too. The clearTrace() function simply clears the TraceConsole element, if found. The traceDump() function traces all the information about an object including its properties. Internally this function uses the trace() function so that we can have the information logged in the browser’s debugging console, and in the TraceConsole element (if it exists). MicrosoftAjax.debug.js You might have wondered why the Microsoft AJAX Library comes with both release and debug version of the JavaScript file. The major features of the debug version of the library files are:  The script is nicely formatted. The names of variables are not obfuscated. The script contains code comments. Some of the functions have the optional summary data that will be used by Visual Studio “Orcas” for code auto-completion. The script outputs debugging-friendly information. Parameters are validated. Once the development stage is finished, you can switch your application to the release version of the script (MicrosoftAjax.js), which is smaller and doesn’t contain the debugging features presented above. Perhaps the most interesting features of the debug version are the last two: debugging-friendly information and parameter validation. Anonymous Functions vs. Pseudo-Named Functions We will explain these two concepts by taking a look at how different functions are defined in the debug and release version of the library. The debug version of the library contains: function Sys$_Debug$assert(condition, message, displayCaller) {   ...}Sys._Debug.prototype = {  assert: Sys$_Debug$assert,  ...} and: String.format = function String$format(format, args) {...} In the release version of the library we have: Sys._Debug.prototype = {  assert: function(c, a, b) {  ...} and: String.format = function() {...} In the release version, we have methods that are anonymous functions. This means that within a debugger stack trace the method name will read JScript anonymous function. This is not very useful for debugging purposes, is it? Call Stack showing anonymous functions However, the debug version of the library uses the dollar-syntax to provide alias names for our functions: String$format for String.format and Sys$Debug$assert for Sys.Debug.assert. When using the debug version of the file, the stack trace would look like: Call Stack showing named functions We can still notice some anonymous functions as they are the result of creating callback or delegate functions. The example shows two different ways of coding:  In the debug version, the function is declared outside the prototype and then referenced in the prototype declaration. In the release version, the declaration is done directly where the function is declared (outside or inside the prototype). Parameters Validation Another interesting feature that has not been documented in the Microsoft AJAX Library documentation is that of parameters validation. Type safety is one of the typical problems when it comes to using JavaScript. Although the dynamic type features are really useful, sometimes we might really want to make sure that a parameter or object is of a certain type. To check the data type of an object, you can try converting the object to the desired type, or using the methods defined by Type. Fortunately the Microsoft AJAX Library has a function that does the dirty work for us: Function._validateParams(). The class diagram in figure below shows the _validateParameter() and _validateParams() methods of the Function class. The Function class The Function._validateParams() function, even if it is declared as private (by convention, using the leading underscore), can be used by our scripts as it is used throughout the debug version of the Microsoft AJAX Library. Here’s an example of using this function: function Sys$_Debug$fail(message) {/// <param name="message" type="String" mayBeNull="true"></param>   var e = Function._validateParams(arguments,          [ {name: "message", type: String, mayBeNull: true} ]);   if (e) throw e; This shows how the parameter for the fail() function is validated as a String. We can also see the additional code comments inside the function, which are meant to be used by the IntelliSense feature in Visual Studio “Orcas” to check for the correctness of the parameter types. While the first parameter of _validateParams() represents an array of parameters to be checked, the second parameter is an array of JSON objects describing the validation rules for the array of parameters. Each JSON object contains a validation rule for a parameter. The JSON object is a dictionary of keys and values. The list of keys that can be used is described in the table that follows. Key Description name The name of the parameter type The allowed type for this parameter (ex: String, Array, Function, Sys.Component, etc.) mayBeNull Boolean value indicating whether this parameter can be passed as null or not domElement Boolean value indicating whether this parameter is a DOM element or not integer Boolean value indicating whether this parameter should have an integer value or not optional Boolean value indicating whether this parameter is optional or not parameterArray Boolean value indicating whether this parameter should be an Array or not elementType The allowed type for each element of an array (type must be Array) elementMayBeNull Boolean value indicating whether an array element could have null or not (type must be Array) elementDomElement Boolean value indicating whether each element of an array is a DOM element (type must be Array) elementInteger Boolean value indicating whether each element of an array should have an integer value (type must be Array) The function returns an error message if the parameters don’t validate and the error is typically thrown like this: if (e) throw e; This exception could be caught and the appropriate measures taken programmatically. If the exception is not caught, the error will pop up in the debugging console of the browser.
Read more
  • 0
  • 0
  • 3121

article-image-modeling-orchestration-and-choreography-service-oriented-architecture
Packt
22 Oct 2009
30 min read
Save for later

Modeling Orchestration and Choreography in Service Oriented Architecture

Packt
22 Oct 2009
30 min read
  Choreography versus Orchestration Choreography and orchestration, in an SOA context, pertain to the use of processes that span multiple participants, with message traffic moving in all directions according to a complex set of rules. Choreography and orchestration are attempts to coordinate or control all of this activity. They attack the problem by putting rigor on how message exchanges are represented, and by organizing the overall process using the right set of control flow patterns. Use cases in this area can be inter-organizational (for example, B2B commerce involving buyer, seller, and wholesaler), or intra-organizational if the organization is large enough and the participants act as separate organizations (for example, bank account processes spanning the front office, the back office, and the fraud department). By convention, choreography describes the global protocol governing how individual participants interact with one another. Each participant has its own process, but choreography is a master process that acts as a kind of traffic cop. Significantly, the choreography process does not actually run. It is not a central broker in the live message exchange, but merely a message exchange protocol. If the participants follow the protocol, the live exchange will run as smoothly as if there were a central broker. 'Traffic cop' is not exactly right then; choreography is more like a set of traffic rules. To mix metaphors, choreography teaches the participant processes how to dance as a group. The process for each participant is referred to as an orchestration process, whose principal job is to build a flow of control around (that is, to orchestrate) its interactions with partners. Orchestration processes are difficult to model, especially those faced with complex combinations of inbound events. If the process is subject to choreography, its structure can be derived from the choreography; in fact, as we'll see, there are tools that can generate skeletal orchestration processes from choreography definitions. The idea is simple: the choreography tells the complete story, so the participant can determine its role by isolating the parts in which it's involved. Not all orchestrations, alas, have a choreography to guide them (not all inter-organizational domains have a precise protocol defined). If the use case is sufficiently complex, the participant ought to create its own choreography anyway, not to share with its partners but simply to improve its own understanding of its orchestration. An orchestration process has public and private activities. The public activities are those that are required by the choreography. Private activities are there to meet internal requirements, but are not visible to partners. The next figure shows the public activities of the orchestration process for an energy retailer. The steps shown (for example, Send Request to Distributor) are those required by the enrollment choreography, in which the retailer is but one participant. The next figure shows the same process with private steps (for example, Update Account) included. In the figure, steps marked with a P are public steps. We examine the energy example in detail in this article. Web Services Choreography Description Language (WS-CDL) is the leading choreography language; Business Process Execution Language (BPEL) is the dominant process orchestration language. Although these XML-based languages feature a similar flow-oriented design style, only BPEL is meant to have an actual runtime platform: BPEL processes run; WS-CDL choreographies are protocols. BPEL is better known than WS-CDL in part because orchestration is more prevalent than choreography. BPEL's user community is much larger than WS-CDL's. Today, every company is building an SOA platform, and if they don't use BPEL as their SOA orchestration language, they use something similar. The user community for choreography consists of industry committees that publish protocols such as the enrollment and funds transfer choreographies we discuss in this article. Choreography might also work as part of a large organization's enterprise architecture, helping to sort out the communication of the organization's numerous systems. Few of these committees use WS-CDL to document their protocols anyway. Choreography is more often documented less formally using English descriptions, flowchart diagrams, and an XML message schema. Examples-Energy Enrollment and Email Bank Transfer The two examples from industry that showcase our technique for modeling choreography and orchestration are the enrollment of customers with retailers in a deregulated energy market and the procedure for transferring funds by email between two banks. In the energy market for a state or small country there are three parties: customers (who use electricity to power their homes), retailers (who sell electricity to customers), and the distributor (who supplies the electricity). Before deregulation, the distributor sold electricity directly to customers; there were no retailers back then. Deregulation introduced competition and broke up the distributor's monopoly. Customers can now buy electricity from one of many competing retailers. The distributor is now merely a supplier, having moved out of the retail sales business. When a customer enrolls with a retailer, the retailer uses the following protocol to complete the enrollment: The retailer submits the customer's request for enrollment to the distributor. The distributor responds in one of the three ways. If there is a problem with the request (for example, the customer has another enrollment in progress, or the customer has been flagged for fraud), the distributor sends a rejection to the retailer. If the request is valid and the customer is not currently enrolled with a retailer, the distributor sends an acceptance to the retailer. If the customer is currently enrolled with a competing retailer but intends to switch, the distributor sends a notice of pending switch to both the retailers. In the acceptance case, there is a 10-day waiting period during which the customer may cancel the enrollment. To cancel, the customer contacts the retailer, who forwards the cancellation request to the distributor. Assuming the customer does not cancel, at the end of the waiting period, the distributor sends a completion event to the retailer. The customer is now enrolled with the retailer. In the switch case, there is also a 10-day waiting period. To cancel, the customer contacts the initiating retailer (that is, the retailer to whom the customer is switching). The initiating retailer forwards the cancellation to the distributor, who then sends completion events to both retailers indicating that the customer will remain enrolled with the original retailer. Assuming the customer does not cancel, at the end of the waiting period, the distributor sends completion events to both retailers indicating that the customer is now enrolled with the initiating retailer. Email bank transfer is a protocol for wiring money by email. It works as follows: The person sending the money contacts his bank (the Sender bank), specifying from which account to draw the funds, how much money to send, and the name and email address of the recipient. The Sender bank sets aside the amount and sends an email to the recipient with instructions on how to complete the transfer. The Sender bank sets aside the amount and sends an email to the recipient with instructions on how to complete the transfer. The Recipient bank submits the transfer request to the Sender bank. The Sender bank accepts, and the funds are moved into the recipient's account, completing the transfer. At any point, either the sender or recipient may cancel the transfer, and the transaction is automatically canceled if not completed within 30 days. On cancellation, the funds are returned to the sender's account. (We assume both banks are members of the email transfer programme.) The following figure shows the most common scenarios in these examples: Modeling Choreography in BPMN In BPMN, two possible models for choreography are as follows: Invisible hub: Although choreography is fundamentally decentralized, we imagine there is a central hub through which all messages pass, and model the choreography as the process of that hub. Sum of parts: The public process of each participant (that is, the process containing steps required by the choreography, with private steps omitted) is drawn in a swim lane. Message flow (dashed lines) is used to show inter-participant communication. A sum-of-parts model for the enrollment choreography is shown in next figure. There are three swim lanes in the diagram: one for the distributor (referred to as Distributor), one for the initiating retailer (referred to as Retailer), and one for the current retailer (referred to as CurrentRetailer). Each lane contains the public process of the participant. The dashed arrows show the flow of messages between participants. The enrollment choreography is, according to this approach, the combination of the public processes of each participant plus the message flow that connects them. The choreography begins when the customer enrolls with the retailer (Cust Enrolls in the Retailer lane). The retailer then submits the enrollment request to the distributor by calling Dist.enroll. This call sends a message to the distributor, which triggers the event Enroll (the first step in the Distributor lane). The Distributor process is now underway, and it responds to the enrollment request either by rejecting the request, accepting it, or notifying the initiating retailer and the current retailer of a pending switch. The distributor rejects by calling Ret.reject, and, as the dashed line signifies, triggers the event Dist.reject in the retailer. The remaining steps are straightforward. The sum-of-parts method is intuitive, and variations on it can be found in business process literature (in the WSCI and BPMN specifications, for example). Sum-of-parts, however, has two disadvantages. First, the message flow creates an indecipherable clutter, making complex choreographies almost impossible to read; the swim lanes, for their part, use a lot of real estate. Aesthetics aside, sum-of-parts fails to present a global, consolidated view of the choreography. We grow bug-eyed trying to keep track of what each participant is doing. We are forced to watch each dancer rather than the group as a whole. The invisible-hub representation is comparatively compact. The next figure, which shows the enrollment choreography as a hub, has fewer steps than the sum-of-parts equivalent, and it makes do without lanes or dashed lines. The hub works as you would expect a hub to work: it listens for inbound events and routes them to their intended recipients. The act of receiving an event and sending it elsewhere is a single unit of work (shown in the figure as a rounded box with a dashed line), known as an interaction. The hub choreography represents the communication of its participants as a process of interactions. Before walking through this process, consider the following notational conventions: The event with a thin border (Ret.enroll(Dist)) is the process' start event. Events with a double-line border (for example, Dist.reject(Ret)) are intermediate events, which occur over the course of the process. Intermediate events can be used in three ways: for cancellation, for deferred choice, or simply to wait for the next message before continuing. The enrollment hub has examples of the latter two forms. We'll come back to cancellation while discussing the email transfer hub. Deferred choice, also known as an event pick, uses a diamond containing an inscribed star (known as an event-based gateway) with arrows leading to a set of intermediate events. The intent is to wait for one of those events to occur, execute its activities, and discard the remaining events. There are three deferred choices in the enrollment hub. The first occurs in three steps, and selects one of the three events: Dis.reject(Ret), Dist.accept(ret), or Dist.pendingSwitch(Ret, CurrRet). If, say, Dist.reject(Ret) occurs first, the activity Ret1.reject(Dist) is executed. The intermediate event Dist.switchCompleteCurrent(Ret, CurrRet) simply waits for something to happen before continuing. This event is sandwiched between the activities Dist.cancel(Ret) and Ret.switchCompleteCurrent, CurrRet.switchCompleteCurrent(Dist). Thus, when the first activity completes, that branch of the process waits for the event to occur before continuing with the second activity. Events have labels of the form Sender.msg (Recipients), meaning that the event received by the hub is a message from the sender bound for the specified recipients. (There must be at least one.) Thus, Dist.switchCompleteCurrent(Ret, CurrRet) is the message switchCompleteCurrent from the distributor (Dist) to both the initiating retailer (Ret) and the current retailer (CurrRet). Send tasks (rounded boxes with a straight border) are labeled Recipient.msg(Sender), meaning that hub is sending the specified message to the recipient and is indicating that the message originated with the specified sender. In Dist.enroll(Ret), for instance, the hub sends the message enroll to the distributor (Dist), and is indicating to the distributor that this message came from the retailer (Ret). If the event that preceded it specifies multiple recipients, the send task sends the message to each recipient. Each send counts as one interaction.Ret.pendingSwitch, CurrRet.pendingSwitch (Dist), for example, sends the message pendingSwitch to both the retailer (Ret) and the current retailer (CurrRet), and thus spans two interactions. A rounded box with a dashed border, known in BPMN as a group, pairs up an event and a send task. Thus, the grouping of Ret.enroll(Dist) and Dist.enroll(Ret) means that when the hub receives the message enroll from the retailer bound for the distributor, it sends that message to the distributor, indicating to the distributor that the message originated with the retailer. A group that contains multiple interactions has a label in the top-center of the dashed box indicating the number of interactions. The number of interactions is equal to the number of recipients. The enrollment hub diagram reads as follows: The choreography begins with the interaction in which the retailer sends an enrollment request to the distributor. For convenience, this interaction is labeled a in the figure. Exactly one of the three interactions can happen next: the distributor sends a rejection to the retailer (b); the distributor sends an acceptance to the retailer (c); or the distributor sends a notice of pending switch to both the initiating and current retailers (d). Exactly one of the two interactions can follow acceptance: the retailer sends a cancellation to the distributor e, or the distributor sends a completion event to the retailer (f). In the pending switch case, one of the two interactions follows the notice of pending switch: the initiating retailer sends a cancellation to the distributor (g); or the distributor sends a switch completion event to both the initiating and current retailers indicating that the current retailer won (h). If the switch is cancelled, the distributor sends a switch completion event to both retailers indicating that the initiating retailer won (i). The choreography has 12 interactions assembled in a process flow. (There are nine groups, but three of them have two interactions each.) Reading the diagram means spotting the 12 interactions and traversing the control flow that connects them. The email transfer choreography hub, shown in the next figure, is somewhat more complex. The email transfer hub reads as follows: The choreography begins when the sender submits the transfer request to the sender bank (a). The sender bank can reject the request (b), or accept it (c). The acceptance event in c is routed to both the sender and the recipient, and thus results in two interactions. The remainder of the hub process is a loop that continues until the transfer is completed. The loop is modeled as a BPMN embedded sub-process labeled Loop. The arched arrow pointing counter-clockwise in the bottom-center of the sub-process box denotes that this sub-process is iterative. In the first step of the loop, the recipient requests her bank to transfer the funds into his or her account (d). The recipient's bank either rejects (e) or accepts (f) the request. In the rejection case, the recipient's bank sends a rejection notice to the recipient. In the next iteration of the loop, the recipient can try again. In the acceptance case, the recipient's bank sends a transfer request to the sender's bank. The sender's bank can either accept (g) or reject (h) the request. In the acceptance case, the sender's bank sends a transferOK message to both the recipient's bank and the sender. The recipient's bank then notifies the recipient (i), and the choreography completes. (The Set Done task sets the loop's continuation condition to false, which causes the loop to exit and the hub process to complete.) In the rejection case, the sender's bank sends a rejectTransfer message to the recipient's bank, and the recipient's bank notifies the recipient of this (j). In the next iteration of the loop, the recipient can try again. While the loop is executing, any of the parties may cancel the request (k). The label in the event *.cancel (SenderBank) informs the hub to listen for a cancel message from any party—the * works as a wildcard—and to route that message to the sender's bank. The sender's bank, in turn, sends an abort message (l) to the sender, the recipient, and the recipient's bank (the bank into which the recipient is currently requesting the transfer). Interaction (k) is an example of a cancellation intermediate event; it terminates the loop and transition into a series of cancellation activities. Choreographies are not executable, as we discussed previously. A choreography is a protocol, a set of traffic laws. It is, emphatically, not a central hub through which all participant interactions flow. Our hub model is merely a specification of how the individual participants should communicate. There are countless senders, recipients, and banks in the world of email transfer, but there is no hub that helps them talk to each other. The invisible hub for email transfer is merely a model; it is every bit as hypothetical as the invisible hand of Adam Smith's free-market economy. The economy is self-powered, and does not require the intervention of a hand; email transfer goes on without a hub. Still, the BPMN hub model is more than an informative picture. As we'll see, it maps easily to WS-CDL, and it serves as the basis for the generation of participant stubs and a choreography 'protocol' tester. Our BPMN method is practical and built with implementation in mind. Choreography modeling is also a hot topic in the academic world. Useful papers in this arena include Inheritance of Interorganizational Workflows: How to agree to disagree without loosing control? (Wil van der Aalst," BETA Working Paper Series, BP46, Eindhoven University, http://is.tm.tue.nl/staff/wvdaalst/publications/p109.pdf) and 'Let's Dance' (servicechoreographies.com, http://sky.fit.qut.edu.au/~dumas/LetsDance/01-Overview.html). The Invisible Hub in BPEL BPEL is principally an orchestration language, as just discussed, but it can also be used to model invisible hub choreographies. The code shown in the next figure is a simplified version of an actual BPEL implementation of the enrollment hub. The mapping from the BPMN hub to this BPEL implementation is straightforward: The event that starts the choreography in BPMN (Ret.enroll(Dist)) is receive that creates the BPEL process instance, marked as Start Event in the figure. An intermediate event that simply waits for a message between activities (for example, Dist.switchCompleteCurrent (Ret, CurrRet) in the BPMN model) is a BPEL receive, such as the line marked Intermediate Event in the figure. Deferred choice is a BPEL pick. The events in the choice are onMessage handlers. For example, the deferred choice in the BPMN model of Dist.reject(Ret), Dist.accept(Ret) and Dist.pendingSwitch(Ret, CurrRet) is the pick marked as Deferred Choice in the figure. The handlers are the three onMessage blocks that sit underneath the pick. Send tasks are BPEL invoke activities. For example, Dist.enroll(Ret) in the BPMN representation becomes the invoke in the line marked Send Task in the figure. The set of partner links used in the BPEL process is the union of all sender and recipient participants in the hub. Many partner links are bidirectional: they can either call the BPEL process or the BPEL process can call the partner link. The three partner links in this example, which are referred to in each receive, invoke, and onMessage tag are Ret, Dist, and CurrRet. BPEL supports dynamic partner links (where the BPEL process determines the physical address of its partner service at runtime). The series of four steps marked Dynamic partner links in the figure provides an example. The initial receive is a message from the distributor intended for one of the two retailers (either the current or the initiating retailer). The invoke that follows sends the message to that retailer. The endpoint of that retailer is resolved at runtime, based on the contents of the receive message. The next receive is a message from the distributor intended for the second retailer, and the invoke that follows sends the message to that retailer, again resolving the endpoint at runtime. In the majority of BPEL processes, partner links are resolved at deployment time, but that approach does not work in scenarios like ours. An interaction in which the sender sends to N recipients is modeled in BPEL as N separate inbound events and invokes. The series of four steps discussed in the previous bullet (and marked with Send to Multiple in the figure) provides an example. These steps model the activity Dist.switchCompleteCurrent (Ret, CurrRet) from the BPMN hub. In the BPEL code, the effect of the distributor sending the message switchCompleteCurrent to both the initiating and current retailers is achieved by having the hub receive the message from the distributor twice (using a receive), in each case forwarding the message (using an invoke) to one of the retailers. Dynamic partner links are used to resolve the endpoint of the recipient. The figure maps lines of code in the BPEL hub to interaction groups in the BPMN model. The first two lines, for example, represent group A. The reader can easily verify the mapping for groups B to I. There are two advantages to having the hub model in BPEL form: BPEL's XML form is an alternative to the leading XML choreography representation, WS-CDL (discussed in the next section). If we require an XML representation of choreography, BPEL might be a better choice than WS-CDL, because it is more familiar and has broader tool support. The BPEL hub is executable! There are numerous BPEL runtime platforms that can run this process as an actual hub. Granted, choreographies are not meant to run as part of the live exchange of actual participants, but having an executable version enables two important types of testing, shown in the next figure: unit testing of the choreography itself, and protocol testing of a particular participant. In unit testing, we build a Test Harness, driven by scripted scenarios, that sends messages to the hub and compares responses received with those expected. In protocol testing, we build the public process of a participant (say the retailer), but point it to the hub rather than its actual partners. We can embellish the hub to use test scripts to control how it responds. Once we have tested all of the scenarios and verified that the participant behaves as required, we can point the participant process to the real partners and go live Choreography in WS-CDL with Pi4SOA The description of choreography in WS-CDL with P14SOA is as follows: Defining Roles and Relationships Web Services Choreography Description Language (WS-CDL) is a specification from the W3C (Web Services Choreography Description Language Version 1.0, http://www.w3.org/TR/ws-cdl-10) for building choreographies in XML form. Like our invisible hub model, WS-CDL takes the global view: a choreography is not the sum of the public processes of its participants, but a single control flow of interactions. The WS-CDL language is exceedingly rich and best learned by example. In this section, we study how the enrollment choreography is represented in WS-CDL. Rather than building the choreography's XML from scratch, we use a visual modelling tool known as pi4SOA. pi4SOA, an open-source implementation that plugs into Eclipse, is one of the few WS-CDL implementations available today. The first step in building a WS-CDL choreography is to define participants and their structural relationships. The following figure shows the enrollment choreography open in the Participants, Roles, and Relationships tab of the pi4SOA editor.   There are five participants (shown with building icons) in the figure: Distributor, Retailer, CurrentRetailer, Customer (to model a customer's interaction with a retailer), and DistributorBizCal (a subsystem of the distributor to model the management of business calendars for completion and switch periods). Each participant has a role of the same name (designated by a stick-man icon), and each role has a behavior named for its role: Distributor's behavior is DistributorBehavior, Retailer's behaviour is RetailerBehavior, and so on. In WS-CDL, a behavior is a web service interface, and a role is a group of behaviors. A role can have multiple behaviors and a participant can have multiple roles. In our case, each participant has one role and one participant. The lines connecting roles are called relationships. There are four relationships: RD is the relationship between Retailer and Distributor, CRD the relationship between CurrentRetailer and Distributor, RC the relationship between Retailer and Customer, and DInt the relationship between Distributor and DistributorBizCal. When two roles have a relationship, they can interact by calling each other's services. The next figure shows the Base Types tab of the choreography editor. To the participants, roles, and relationships defined above, we add four important elements: information types, tokens, token locators, and channel types. An information type is an XML data type (generally based on an XML schema) exchanged during interactions. A token is a field in an information type. A token locator defines how to extract—generally using an XPath expression—the token from the information type. Our choreography has one information type, called EnergyMsg with five tokens and token locators (custID, retailer, txID, currentRetailer, and reason). A channel type is an inbound communication endpoint for a role behavior. In the enrollment choreography, there are channels for the retailer, current retailer and distributor. Each channel type is configured for one-way asynchronous requests only. Hence, Retailer receives requests on its RetailerChannel; CurrentRetailer receives requests on its CurrentRetailerChannel; and Distributor receives requests on its DistributorChannel. Combining our definitions of relationships and channels, we have the following communication structure: In the relationship RD, Retailer sends to Distributor on DistributorChannel, and Distributor sends to Retailer on RetailerChannel   In the relationship CRD, Distributor sends to CurrentRetailer on CurrentRetailerChannel. (CurrentRetailer could also send to Distributor on DistributorChannel, but the use case does not require it.) In the relationship RC, Customer sends to Retailer on RetailerChannel. (Customer does not have a channel, so the reverse direction is not permitted.) In the relationship DInt, DistributorBizCal sends to Distributor on DistributorChannel. (DistributorBizCal does not have a channel, so the reverse direction is not permitted.) Building a Control Flow of Interactions The next figure shows the overall control flow that defines the behaviour of the choreography. There are three steps. The first, RequestC2R, is an interaction in which the Customer participant sends an enrollment request to the Retailer participant. The request has the information type EnrollmentMsg, and is sent on RetailerChannel as part of the RC relationship. In the interaction that follows, RequestR2D, the retailer forwards that request to the distributor; or, in the language of WS-CDL, Retailer sends the request with information type EnrollmentMsg on the DistributorChannel as part of the RD relationship. The step that follows, enrollmentResult, is a flow construct known as a choice. There are three possible outcomes of an enrollment request—acceptance, rejection, or a pending switch. The choice allows exactly one to occur. The next figure shows the acceptance and rejection paths; the switch path is omitted for brevity. The rejection path (housed in a sequence labelled rejectEnrollment) has one interaction, RejectD2R, in which the distributor sends a rejection message to the retailer. The more complicated acceptance path is housed in the sequence labelled newEnrollment, which begins with the interaction in which the distributor notifies the retailer that the enrollment is accepted (AcceptD2R). Next is a silent action, setCompletionTimer, in which the distributor sets a timer that expires at the end of the ten-day cancellation period. A silent action in WS-CDL is a private operation performed by a role. The acceptance path has a nested choice, labelled completionPeriod, which documents the two possible outcomes for an accepted enrolment: periodExpired is a sequence that specifies what happens when the ten-day timer expires, and cancel handles the case in which the customer cancels the enrollment during the cancellation period. Each path contains two interactions. In the periodExpired sequence, the periodExpired interaction (sent from DistributorBizCal to Distributor by the DInt relationship) notifies the distributor that time is up, whereupon the distributor sends a completion event to the retailer (CompleteD2R). In the cancel sequence, the customer cancels with the retailer (CancelC2R by the RC relationship), and the retailer, in turn, cancels with the distributor (CancelR2D by the RD relationship). The following is a snippet of the WS-CDL XML encoding of the enrollment choreography, covering the acceptance case only. For the sake of simplicity, numerous details are omitted: <package name="EnergyChoreo">   <choreography name="main" root="true">     <sequence>       <!-- Cust sends request to retailer -->       <interaction channelVariable="tns:retailerChannel"                    name="RequestC2R" operation="enroll">         <participate fromRoleTypeRef="tns:Customer"                      relationshipType="tns:RC" toRoleTypeRef="tns:Retailer"/>       </interaction>       <!-- Retailer sends request to distributor -->       <interaction channelVariable="tns:distributorChannel"                    name="RequestR2D" operation="enroll">         <participate fromRoleTypeRef="tns:Retailer"                relationshipType="tns:RD" toRoleTypeRef= "tns:Distributor"/>       </interaction>       <!-- Choose what comes next -->       <choice>         <!-- Path taken if distributor rejects -->         <sequence>           <!-- This is the interaction that heads the reject path -->             <interaction name="RejectD2R" operation="reject">             </interaction>         </sequence>         <!-- Path taken if distributor accepts -->         <sequence>           <!-- This is the interaction that heads the accept path -->             <interaction name="AcceptD2R" operation="accept">             </interaction>             <silentAction name="setCompletionTimer"                           roleType="tns:Distributor">             <choice>               <!-- Accept subpaths omitted -->             </choice>          </sequence>          <!-- Omitted: switch path -->       </choice>     </sequence>   </choreography> </package> The two key elements in this example are choice and interaction. They are mapped to our hub model as follows: A receive-send pair in the hub is a WS-CDL interaction. In WS-CDL, a relationship is defined between sender and recipient, and the recipient has a channel on which the sender sends the message. An example of this is the interaction shown in bold from the customer (fromRoleTypeRef="tns: Customer") to the retailer (toRoleTypeRef="tns:Retailer") on the RC relationship (relationshipType="tns:RC"). The event arrives on the retailer's channel (channelVariable="tns:retailerChannel"). A deferred choice in the hub is a choice structure in WS-CDL. Generally, a path in the choice is a sequence. The set of events from which we are choosing is the set of first interactions on each path. The main choice structure in the choreography, shown in bold, has two interactions from which to choose: acceptance and rejection interactions (also shown in bold). The interaction that actually occurs determines which path is taken.   Generating a BPEL Role Process In addition to producing conformant WS-CDL code, pi4SOA's capabilities include scenario testing and BPEL and Java endpoint generation. The BPEL generation feature is especially useful, as BPEL is a suitable implementation choice to build orchestration process of a given participant. Here, in pseudo-code, is the BPEL process that pi4SOA generates for the distributor: <process>   <sequence>     <receive operation="enroll" partnerLink="RD"              portType="DistributorBehavior"/>       <!-- Dist receives interaction -->     <switch name="enrollmentResult"> <!-- Dist choice is switch -->       <case condition="accepted">         <sequence>           <invoke operation="accept" partnerLink="RD"                   portType="RetailerBehavior"/> <!-- Dist is sender -->           <scope name="setCompletionTimer"/>           <pick name="completionPeriod">             <onMessage operation="periodExpired" partnerLink="DInt"                        portType="DistributorBehavior">               <sequence>                 <invoke operation="complete" partnerLink="RD"                         portType="RetailerBehavior"/>               </sequence>             </onMessage>             <onMessage operation="cancel" partnerLink="RD"                        portType="DistributorBehavior"/>           </pick>         </sequence>       </case>       <case condition="rejected ">         <invoke operation="reject" partnerLink="RD"                 portType="RetailerBehavior"/>       </case>       <case condition="switch">         <!-- omitted -->       </case>   </switch> </sequence> </process> Two salient features of this process are the mapping of interactions and the conversion of the WS-CDL choice to a BPEL switch as follows: An interaction in which the distributor is the sender is a BPEL invoke activity whose partner link is the WS-CDL relationship and whose port type is the recipient's behavior. The operation element in the invoke matches the one specified in the interaction. The invoke shown in bold, for example, which is sent to the retailer, has partner link RD, port type RetailerBehavior, and operation accept. An interaction in which the participant is the recipient is either a receive activity or an onMessage handler in a pick. The partner link is the name of the relationship, and port type is the participant's behavior. The operation element, as before, matches that specified in the interaction. The bolded receive in the BPEL sample is the enroll operation on the partner link RD and port type DistributorBehavior. The WS-CDL choice is a switch for the BPEL distributor process (as the bolded comment in the switch line indicates), because the distributor begins each path of the choice by sending a message. From the distributor's perspective, the choice represents its decision to reject the request, accept it, or initiate a pending switch. Each case in the switch handles one of these possibilities. The retailer, on the other hand, begins each path by waiting for an event from the distributor. From the retailer's point of view, the choice is a pick, as in the following snippet: <pick name="enrollmentResult"> <!-- For Ret, choice is a pick -->   <onMessage operation="accept" partnerLink="RD"              portType="RetailerBehavior">     <!-- code omitted -->   </onMessage>   <onMessage operation="reject" partnerLink="RD"              portType="RetailerBehavior" />   <onMessage operation="pendingSwitch" partnerLink="RD"              portType="RetailerBehavior" >     <!-- code omitted -->   </onMessage> </pick> We have only scratched the surface of WS-CDL. Other notable capabilities are state alignment, coordination, and channel passing. WS-CDL's supporters boast that their language has its foundations in the Pi Calculus, a mathematical scheme for describing concurrent processes and how they pass messages to each other. Robin Milner, the mathematician who devised the Pi Calculus, is an advisor to the WS-CDL working group. Sadly, WS-CDL has not gained much traction in the field. There are scant tools to build WS-CDL choreographies and, frankly, not many use cases that require choreography. Few people who practice SOA technology have even heard of this language. WS-CDL is winning the mathematics battle but losing the marketing war. Summary Choreography is the global protocol governing the interaction of SOA processes partnering to achieve some business ends. An orchestration process is a process whose principal job is to build a flow of control around its interactions with partners. WS-CDL is the dominant choreography standard. BPEL is the dominant orchestration standard. Both standards provide a way to build process flows in an XML form, though only BPEL processes are meant to actually execute. The modeling tool pi4SOA is ideal for building WS-CDL examples. Key WS-CDL elements are interaction (which corresponds to the receive-send pair in the invisible hub) and choice (a kind of deferred choice in the choreography's flow of control. pi4SOA generates skeletal BPEL code for each participant in the choreography.
Read more
  • 0
  • 0
  • 7700
article-image-creating-accessible-tables-joomla
Packt
22 Oct 2009
5 min read
Save for later

Creating Accessible Tables in Joomla!

Packt
22 Oct 2009
5 min read
Creating Accessible Tables Tables got a bad review in accessibility circles, because they used to create complex visual layouts. This was due to the limitations in the support for presentational specifications like CSS and using tables for layout was a hack—that worked in the real world—when you wanted to position something in a precise part of the web page. Tables were designed to present data of all shapes and sizes, and that is really what they should be used for. The Trouble with Tables So what are tables like for screen reader users? Tables often contain a lot of information, so sighted users need to look at the information at the top of the table (the header info), and sometimes the first column in each row to associate each data cell. Obviously this works for sighted users, but in order to make the tables accessible to a screen reader user we need to find a way of associating the data in each cell with its correct header so the screen reader can inform the user which header relates to each data cell. Screen reader users can navigate between data cells easily using the cursor keys. We will see how to make tables accessible in simple steps. There are methods of conveying the meaning and purpose of a table to the screen reader user by using the caption element and the summary attribute of the table element that you will find more on in the next section. We will learn how to build a simple table using Joomla! and the features contained within the WYSIWYG editors that can make the table more accessible. Before we do that though I want you to ask yourself about why you want to use tables (though sometimes it is unavoidable) and what forms should they take. Simple guidelines for tables: Try to make the table as simple as possible.    If possible don't span multiple cells etc. The simpler the table, the easier it is to make accessible.    Try to include the data you want to present in the body text of your site. Time for Action—Create an Accessible Table (Part 1) In the following example we will build a simple table that will list the names of some artists, some albums they have recorded, and the year in which they recorded the albums. First of all click the table icon from the TinyMCE interface and add a table with a suitable number of columns and rows.            By clicking on the Advanced tab you will see the Summary field. The summary information is very important. It provides the screen reader user a summary of the table. For example, I filled in the following text: "A list of some funk artists, my favorite among their records, and the year they recorded it in". My table then looked as follows: What Just Happened? There is still some work to be done in order to make the content more accessible. The controls that the WYSIWYG editor offers are also a little limited so we will have to edit the HTML by hand. Adding the summary information is a very good start. The text that I entered "A list of some funk artists, my favorite among their records, and the year they recorded it in." will be read out by the screen reader as soon as it receives a focus by the user. Time for Action—Create an Accessible Table (Part 2) Next we are going to add a Caption to the table, which will be helpful to both sighted and non-sighted users. This is how it's done. Firstly, select the top row of the table, as these items are the table heading. Then click on the Table Row properties icon beside the Tables icon and select Table Head under General Properties. Make sure that the Update current Row is selected in the dialogue box in the bottom left. You will apply these properties to your selected row. If you wish to add a caption to your table you need to add an extra row to the table and then select the contents of that row and add the Caption in the row properties dialogue box. This will tell the browser to display the caption text, in this case Funky Table Caption, else it will remain hidden. What Just Happened? By adding caption to the table, you provide useful information to the screen reader user. This caption should be informative and should describe something useful about the table. As the caption element is wrapped in a heading it is read out by the screen reader when the user starts exploring the table—so it is slightly different to the summary attribute, which is read out automatically. Does it Work? What we just did using the WYSIWYG editor, TinyMCE, is enough to make a good start towards creating a more accessible table, but we will have to work a little more in order to truly make the table accessible. So we will now edit the HTML. The good news is that you have made some good steps in the right direction and the final step is of associating the data cells with their suitable headers, as this is something that we cannot really do with the WYSIWYG editor alone, and is essential to make your tables truly accessible.
Read more
  • 0
  • 0
  • 2244

article-image-migration-apache-lighttpd
Packt
22 Oct 2009
7 min read
Save for later

Migration from Apache to Lighttpd

Packt
22 Oct 2009
7 min read
Now starting from a working Apache installation, what can Lighttpd offer us? Improved performance for most cases (as in more hits per second) Reduced CPU time and memory usage Improved security Of course, the move to Lighttpd is not a small one, especially if our Apache configuration makes use of its many features. Systems tied into Apache as a module may make the move hard or even impossible without porting the module to a Lighttpd module or moving the functionality into CGI programs, if possible. We can ease the pain by moving in small steps. The following descriptions assume that we have one Apache instance running on one hardware instance. But we can scale the method by repeating it for every hardware instance. When not to migrateBefore we start this journey, we need to know that our hardware and operating systems support Lighttpd, that we have root access (or access to someone who has), and that the system has enough space for another Lighttpd installation (yes, I know, Lighttpd should reduce space concerns, but I have seen Apache installations munching away entire RAID arrays). Probably, this only makes sense if we plan on moving a big percentage of traffic to Lighttpd. We also might make extensive use of Apache module, which means a complete migration would involve finding or writing suitable substitutes for Lighttpd. Adding Lighttpd to the Mix Install Lighttpd on the system that Apache runs on. Find an unused port (refer to a port scanner if needed) to set server.port to. For example, if port 4080 is unused on our system, we would look for server.port in our Lighttpd configuration and change it to: server.port = 4080 If we want to use SSL, we should change all occurrences of the port 443 to another free port, say 4443. We assume our Apache is answering requests on HTTP port 80. Now let's use this Lighttpd instance as a proxy for our Apache by adding the following configuration: server.modules = (#..."mod_proxy",#...)#...proxy.server = ("" => ( # proxy everythinghost => "127.0.0.1" # localhostport => "80")) This tells our Lighttpd to proxy all requests to the server that answers on localhost, port 80, which happens to be our Apache server. Now, when we start our Lighttpd and point our browser to http://localhost:4080/, we should be able to see the same thing that our Apache is returning. What is a proxy?A Proxy stands in front of another object, simulating the object by relaying all requests to it. A proxy can change requests on the fly, filter requests, and so on. In our case, Lighttpd is the web server to the outside, whilst Apache will still get all requests as usual. Excursion: mod_proxy mod_proxy is the module that allows Lighttpd to relay requests to another web server. It is not to be confused with mod_proxy_core (of Lighttpd 1.5.0), which provides a basis for other interfaces such as CGI. Usually, we want to proxy only a specific subset of requests, for example, we might want to proxy requests for Java server pages to a Tomcat server. This could be done with the following proxy directive: proxy.server = (".jsp" => ( host => "127.0.0.1", port => "8080" )# given our tomcat is on port 8080) Thus the tomcat server only serves JSPs, which is what it was built to do, whilst our Lighttpd does the rest. Or we might have another server which we want to include in our Web presence at some given directory: proxy.server = ("/somepath" => ( host => "127.0.0.1", port => "8080" )) Assuming the server is on port 8080, this will do the trick. Now http://localhost/somepath/index.html will be the same as http://localhost:8080/index.html. Reducing Apache Load Note that as most Lighttpd directives, proxy.server can be moved into a selector, thereby reducing its reach. This way, we can reduce the set of files Apache will have to touch in a phased manner. For example, YouTube™ uses Lighttpd to serve the videos. Usually, we want to make Lighttpd serve static files such as images, CSS, and JavaScript, leaving Apache to serve the dynamically generated pages. Now, we have two options: we can either filter the extensions we want Apache to handle, or we can filter the addresses we want Lighttpd to serve without asking Apache. Actually, the first can be done in two ways. Assuming we want to give all addresses ending with .cgi and .php to Apache, we could either use the matching of proxy.server: proxy.server = (".cgi" => ( host = "127.0.0.1", port = "8080" ),".php" => ( host = "127.0.0.1", port = "8080" )) or match by selector: $HTTP['url'] =~ "(.cgi|.php)$" {proxy.server = ( "" => ( host = "127.0.0.1", port = "8080" ) )} The second way also allows negative filtering and filtering by regexp — just use !~ instead of =~. mod_perl, mod_php, and mod_python There are no Lighttpd modules to embed scripting languages into Lighttpd (with the exception of mod_magnet, which embeds Lua) because this is simply not the Lighttpd way of doing things. Instead, we have the CGI, SCGI, and FastCGI interfaces to outsource this work to the respective interpreters. Most mod_perl scripts are easily converted to FastCGI using CGI::Fast. Usually, our mod_perl script will look a lot like the following script: use CGI;my $q = CGI->new;initialize(); # this might need to be done only onceprocess_query($q); # this should be done per requestprint response($q); # this, too Using the easiest way to convert to FastCGI: use CGI:Fast # instead of CGIwhile (my $q = CGI:Fast->new) { # get requests in a while-loopinitialize();process_query($q);print response($q);} If this runs, we may try to put the initialize() call outside of the loop to make our script run even faster than under mod_perl. However, this is just the basic case. There are mod_perl scripts that manipulate the Apache core or use special hooks, so these scripts can get a little more complicated to migrate. Migrating from mod_php to php-fcgi is easier — we do not need to change the scripts, just the configuration. This means that we do not get the benefits of an obvious request loop, but we can work around that by setting some global variables only if they are not already set. The security benefit is obvious. Even for Apache, there are some alternatives to mod_php, which try to provide more security, often with bad performance implications. mod_python can be a little more complicated, because Apache calls out to the python functions directly, converting form fields to function arguments on the fly. If we are lucky, our python scripts could implement the WSGI (Web Server Gateway Interface). In this case, we can just use a WSGI-FastCGI wrapper. Looking on the Web, I already found two: one standalone (http://svn.saddi.com/py-lib/trunk/fcgi.py), and one, a part of the PEAK project (http://peak.telecommunity.com/DevCenter/FrontPage). Otherwise, python usually has excellent support for SCGI. As with mod_perl, there are some internals that have to be moved into the configuration (for example dynamic 404 pages, the directive for this is server.error-handler-405, which can also point to a CGI script). However, for basic scripts, we can use SCGI (either from http://www.mems-exchange.org/software/scgi/ or as a python-only version from http://www.cherokee-project.com/download/pyscgi/). We also need to change import cgi to import scgi and change CGIHandler and CGIServer to SCGIHandler and SCGIServer, respectively.
Read more
  • 0
  • 0
  • 7421

article-image-linux-thin-client-considering-network
Packt
22 Oct 2009
4 min read
Save for later

Linux Thin Client : Considering the Network

Packt
22 Oct 2009
4 min read
Primary Network Your first thought might be that your current network will work fine with thin clients and that is entirely possible. But your network might be something that has grown through the years and is not that well designed. Your implementation of thin clients then might be a good time to review the design and make upgrades as needed. Personal Computers versus Thin Clients Based on conversations with some hardware vendors, it's clear that most of the testing is done with the expectation that personal computers willbe deployed. The biggest difference is in how the two platforms use the network. When running a personal computer, often software applications are stored on network servers. When you activate an icon, the network pushes the executable down to your PC. Once downloaded into memory, the application runs and then very little interaction takes place until you save a file. Or in other cases, the executables are on the local PC, and network activity is not used until files are saved. If an executable takes a few seconds longer to download, you won't      really notice it when using a personal computer. Some networking devices seem better designed for efficiency of download instead of being designed for the smaller and more plentiful packets of network computing. When you activate a software application on a thin client, the presentation of the user interface is pushed to you from the server, and then all keystrokes and mouse activity are transmitted back and forth to the server in real time. The network needs to be very fast, have low latency, and be configured to pass packets immediately to the servers. Network Design For implementing your network, the network backbone should be Gigabit if possible. Obviously if your solution is for only a small number of users, this might not be required. Ideally fibre optic lines are then run to each of the wiring closets, and each switch should have it's own line. It is advisable to avoid daisy-chaining the switches together in order to avoid any kind of contention between them. The servers are all plugged into the backbone at Gigabit as well. If a server is required away from a centralized computer room, then it is better to run a separate line instead of plugging it into a switch that will be shared with thin clients. It's important to keep the data paths solidly designed so that all of your real-time interaction will not be delayed. X windows, RDP, or Citrix are used to display the user presentation. This means that the software is running on the server, but the image of that software is transmitted over the network. It's important that a strong network exists or repaints of windows will be slower and feel sluggish. This issue will cause people problems, with perceptions that a personal computer can run software faster than a network. A correctly designed network will provide excellent response time and the user community should not even see a difference. Font servers are used to distribute fonts to users. A font server is just a process or application that runs on the server. When a user requests a font, it's sent over the network to the thin client and made available to them immediately. The strength of this design is that all your employees will have the same fonts and while sharing documents, they will render exactly the same way no matter from where you log into the network. Anyone that has shipped documents between personal computers with different fonts, will greatly appreciate this design. When the network is configured correctly, font download and interaction is immediate and undetected by the user community. NFS mounts are used to connect disk drives between Linux servers. This allows applications to share data between the various servers on your network. Response time needs to be excellent to provide very fast file saves and retrievals, at the same time avoiding applications that lock or timeout while trying to interact with files. A review of the possible network problems is provided in the following table: Networking Issue Symptom(s) X windows RDP Citrix Slow repaints of user interfaces Lockups Disconnections Font Servers Slow repaints Wrong fonts in applications Thin Client Slow keyboard response Disconnections Slow repaints NFS Mounts Lockups Slow response in saving files  
Read more
  • 0
  • 0
  • 1539
article-image-enhancing-user-interface-ajax
Packt
22 Oct 2009
32 min read
Save for later

Enhancing the User Interface with Ajax

Packt
22 Oct 2009
32 min read
Since our project is a Web 2.0 application, it should be heavily focused on the user experience. The success of our application depends on getting users to post and share content on it. Therefore, the user interface of our application is one of our major concerns. This article will improve the interface of our application by introducing Ajax features, making it more user-friendly and interactive. Ajax and Its Advantages Ajax, which stands for Asynchronous JavaScript and XML, consists of the following technologies: HTML and CSS for structuring and styling information. JavaScript for accessing and manipulating information dynamically. XMLHttpRequest, which is an object provided by modern browsers for exchanging data with the server without reloading the current web page. A format for transferring data between the client and server. XML is sometimes used, but it could be HTML, plain text, or a JavaScript-based format called JSON. Ajax technologies let code on the client-side exchange data with the server behind the scenes, without having to reload the entire page each time the user makes a request. By using Ajax, web developers are able to increase the interactivity and usability of web pages. Ajax offers the following advantages when implemented in the right places: Better user experience. With Ajax, the user can do a lot without refreshing the page, which brings web applications closer to regular desktop applications. Better performance. By exchanging only the required data with the server, Ajax saves bandwidth and increases the application's speed. There are numerous examples of web applications that use Ajax. Google Maps and Gmail are perhaps two of the most prominent examples. In fact, these two applications played an important role in spreading the adoption of Ajax, because of the success that they enjoyed. What sets Gmail from other web mail services is its user interface, which enables users to manage their emails interactively without waiting for a page reload after every action. This creates a better user experience and makes Gmail feel like a responsive and feature-rich application rather than a simple web site. This article explains how to use Ajax with Django so as to make our application more responsive and user friendly. We are going to implement three of the most common Ajax features found in web applications today. But before that, we will learn about the benefits of using an Ajax framework as opposed to working with raw JavaScript functions. Using an Ajax Framework in Django In this section we will choose and install an Ajax framework in our application. This step isn't entirely necessary when using Ajax in Django, but it can greatly simplify working with Ajax. There are many advantages to using an Ajax framework: JavaScript implementations vary from browser to browser. Some browsers provide more complete and feature-rich implementations, whereas others contain implementations that are incomplete or don't adhere to standards. Without an Ajax framework, the developer must keep track of browser support for the JavaScript features that they are using, and work around the limitations that are present in some browser implementations of JavaScript. On the other hand, when using an Ajax framework, the framework takes care of this for us; it abstracts access to the JavaScript implementation and deals with the differences and quirks of JavaScript across browsers. This way, we concentrate on developing features instead of worrying about browser differences and limitations. The standard set of JavaScript functions and classes is a bit lacking for fully fledged web application development. Various common tasks require many lines of code even though they could have been wrapped in simple functions. Therefore, even if you decide not to use an Ajax framework, you will find yourself having to write a library of functions that encapsulates JavaScript facilities and makes them more usable. But why reinvent the wheel when there are many excellent Open Source libraries already available? Ajax frameworks available on the market today range from comprehensive solutions that provide server-side and client-side components to light-weight client-side libraries that simplify working with JavaScript. Given that we are already using Django on the server-side, we only want a client-side framework. In addition, the framework should be easy to integrate with Django without requiring additional dependencies. And finally, it is preferable to pick a light and fast framework. There are many excellent frameworks that fulfil our requirements, such as Prototype, the Yahoo! UI Library and jQuery. I have worked with them all and they are all great. But for our application, I'm going to pick jQuery, because it's the lightest of the three. It also enjoys a very active development community and a wide range of plugins. If you already have experience with another framework, you can continue using it during this article. It is true that you will have to adapt the JavaScript code in this article to your framework, but Django code on the server-side will remain the same no matter which framework you choose. Now that you know the benefits of using an Ajax framework, we will move to installing jQuery into our project. Downloading and Installing jQuery One of the advantages of jQuery is that it consists of a single light-weight file. To download it, head to http://jquery.com/ and choose the latest version (1.2.3 at the time of writing). You will find two choices: Uncompressed version: This is the standard version that I recommend you to use during development. You will get a .js file with the library's code in it. Compressed version: You will also get a .js file if you download this version. However, the code will look obfuscated. jQuery developers produce this version by applying many operations on the uncompressed .js file to reduce its size, such as removing white spaces and renaming variables, as well as many other techniques. This version is useful when you deploy your application, because it offers exactly the same features as the uncompressed one, but with a smaller file size. I recommend the uncompressed version during development because you may want to look into jQuery's code and see how a particular method works. However, the two versions offer exactly the same set of features, and switching from one to another is just a matter of replacing one file. Once you have the jquery-xxx.js file (where xxx is the version number), rename it to jquery.js and copy it to the site_media directory of our project (Remember that this directory holds static files which are not Python code). Next, you will have to include this file in the base template of our site. This will make jQuery available to all of our project pages. To do so, open templates/base.html and add the highlighted code to the head section in it: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css"type="text/css" /> <script type="text/javascript"src="/site_media/jquery.js"></script></head> To add your own JavaScript code to an HTML page, you can either put the code in a separate .js file and link it to the HTML page by using the script tag as above, or write the code directly in the body of a script tag: <script type="text/javascript"> // JavaScript code goes here.</script> The first method, however, is recommended over the second one, because it helps keep the source tree organized by putting HTML and JavaScript code in different files. Since we are going to write our own .js files during this article, we need a way to link .js files to templates without having to edit base.html every time. We will do this by creating a template block in the head section of the base.html template. When a particular page wants to include its own JavaScript code, this block may be overridden to add the relevant script tag to the page. We will call this block external, because it is used to link external files to pages. Open templates/base.html and modify its head section as follows: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css"/> <script type="text/javascript" src="/site_media/jquery.js"> </script> {% block external %}{% endblock %}</head> And we have finished. From now on, when a view wants to use some JavaScript code, it can link a JavaScript file to its template by overriding the external template block. Before we start to implement Ajax enhancements in our project, let's go through a quick introduction to the jQuery framework. The jQuery JavaScript Framework jQuery is a library of JavaScript functions that facilitates interacting with HTML documents and manipulating them. The library is designed to reduce the time and effort spent on writing code and achieving cross-browser compatibility, while at the same time taking full advantage of what JavaScript offers to build interactive and responsive web applications. The general workflow of using jQuery consists of two steps: Select an HTML element or a group of elements to work on. Apply a jQuery method to the selected group Element Selectors jQuery provides a simple approach to select elements; it works by passing a CSS selector string to a function called $. Here are some examples to illustrate the usage of this function: If you want to select all anchor (<a>) elements on a page, you can use the following function call: $("a") If you want to select anchor elements which have the .title CSS class, use $("a.title") To select an element whose ID is #nav, you can use $("#nav") To select all list item (<li>) elements inside #nav, use $("#nav li") And so on. The $() function constructs and returns a jQuery object. After that, you can call methods on this object to interact with the selected HTML elements. jQuery Methods jQuery offers a variety of methods to manipulate HTML documents. You can hide or show elements, attach event handlers to events, modify CSS properties, manipulate the page structure and, most importantly, perform Ajax requests. Before we go through some of the most important methods, I highly recommend using the Firefox web browser and an extension called Firebug to experiment with jQuery. This extension provides a JavaScript console that is very similar to the interactive Python console. With it, you can enter JavaScript statements and see their output directly without having to create and edit files. To obtain Firebug, go to http://www.getfirebug.com/, and click on the install link. Depending on the security settings of Firefox, you may need to approve the website as a safe source of extensions. If you do not want to use Firefox for any reason, Firebug's website offers a "lite" version of the extension for other browsers in the form of a JavaScript file. Download the file to the site_media directory, and then include it in the templates/base.html template as we did with jquery.js: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css"/> <script type="text/javascript" src="/site_media/firebug.js"> </script> <script type="text/javascript" src="/site_media/jquery.js"> </script> {% block external %}{% endblock %}</head> To experiment with the methods outlined in this section, launch the development server and navigate to the application's main page. Open the Firebug console by pressing F12, and try selecting elements and manipulating them. Hiding and Showing Elements Let's start with something simple. To hide an element on the page, call the hide() method on it. To show it again, call the show() method. For example, try this on the navigation menu of your application: >>> $("#nav").hide()>>> $("#nav").show() You can also animate the element while hiding and showing it. Try the fadeOut(), fadeIn(), slideUp() or slideDown() methods to see two of these animated effects. Of course, these methods (like all other jQuery methods) also work if you select more than one element at once. For example, if you open your user page and enter the following method call into the Firebug console, all of the tags will disappear: >>> $('.tags').slideUp() Accessing CSS Properties and HTML Attributes Next, we will learn how to change CSS properties of elements. jQuery offers a method called css() for performing CSS operations. If you call this method with a CSS property name passed as a string, it returns the value of this property: >>> $("#nav").css("display") Result: "block" If you pass a second argument to this method, it sets the specified CSS property of the selected element to the additional argument: >>> $("#nav").css("font-size", "0.8em") Result: <div id="nav" style="font-size: 0.8em;"> In fact, you can manipulate any HTML attribute and not just CSS properties. To do so, use the attr() method which works in a similar way to css(). Calling it with an attribute name returns the attribute value, whereas calling it with an attribute name/value pair sets the attribute to the passed value. To test this, go to the bookmark submission form and enter the following into the console: >>> $("input").attr("size", "48") Results: <input id="id_url" type="text" size="48" name="url"> <input id="id_title" type="text" size="48" name="title"> <input id="id_tags" type="text" size="48" name="tags"> (Output may slightly differ depending on the versions of Firefox and Firebug). This will change the sizes of all input elements on the page at once to 48. In addition, there are shortcut methods to get and set commonly used attributes, such as val() which returns the value of an input field when called without arguments, and sets this value to an argument if you pass one. There is also html() which controls the HTML code inside an element. Finally, there are two methods that can be used to attach or detach a CSS class to an element; they are called addClass() and removeClass(). A third method is provided to toggle a CSS class, and it is called toggleClass(). All of these class methods take the name of the class to be changed as a parameter. Manipulating HTML Documents Now that you are comfortable with manipulating HTML elements, let's see how to add new elements or remove existing elements. To insert HTML code before an element, use the before() method, and to insert code after an element, use the after() method. Notice how jQuery methods are well-named and very easy to remember! Let's test these methods by inserting parentheses around tag lists on the user page. Open your user page and enter the following in the Firebug console: >>> $(".tags").before("<strong>(</strong>")>>> $(".tags").after("<strong>)</strong>") You can pass any string you want to - before() or after() - the string may contain plain text, one HTML element or more. These methods offer a very flexible way to dynamically add HTML elements to an HTML document. If you want to remove an element, use the remove() method. For example: $("#nav").remove() Not only does this method hide the element, it also removes it completely from the document tree. If you try to select the element again after using the remove() method, you will get an empty set: >>> $("#nav") Result: [] Of course, this only removes the elements from the current instance of the page. If you reload the page, the elements will appear again. Traversing the Document Tree Although CSS selectors offer a very powerful way to select elements, there are times when you want to traverse the document tree starting from a particular element. For this, jQuery provides several methods. The parent() method returns the parent of the currently selected element. The children() method returns all the immediate children of the selected element. Finally, the find() method returns all the descendants of the currently selected element. All of these methods take an optional CSS selector string to limit the result to elements that match the selector. For example, $("#nav").find ("li") returns all the <li> descendants of #nav. If you want to access an individual element of a group, use the get() method which takes the index of the element as a parameter. $("li").get(0) for example returns the first <li> element out of the selected group. Handling Events Next, we will learn about event handlers. An event handler is a JavaScript function that is invoked when a particular event happens, for example, when a button is clicked or a form is submitted. jQuery provides a large set of methods to attach handlers to events; events of particular interest in our application are mouse clicks and form submissions. To handle the event of clicking on an element, we select this element and call the click() method on it. This method takes an event handler function as a parameter. Let's try this using the Firebug console. Open the main page of the application, and insert a button after the welcome message: >>> $("p").after("<button id="test-button">Click me!</button>") (Notice that we had to escape the quotations in the strings passed to the after() method.) If you try to click this button, nothing will happen, so let's attach an event handler to it: >>> $("#test-button").click(function () { alert("You clicked me!"); }) Now, when you click the button, a message box will appear. How did this work? The argument that we passed to click() may look a bit complicated, so let's examine it again: function () { alert("You clicked me!"); } This appears to be a function declaration but without a function name. Indeed, this construct creates what is called an anonymous function in JavaScript terminology, and it is used when you need to create a function on the fly and pass it as an argument to another function. We could have avoided using anonymous functions and declared the event handler as a regular function: >>> function handler() { alert("You clicked me!"); }>>> $("#test-button").click(handler) The above code achieves the same effect, but the first one is more concise and compact. I highly recommend you to get used to anonymous functions in JavaScript (if you are not already), as I'm sure you will appreciate this construct and find it more readable after using it for a while. Handling form submissions is very similar to handling mouse clicks. First, you select the form, and then you call the submit() method on it and pass the handler as an argument. We will use this method many times while adding Ajax features to our project in later sections. Sending Ajax Requests Before we finish this section, let's talk about Ajax requests. jQuery provides many ways to send Ajax requests to the server. There is, for example, the load() method which takes a URL and loads the page at this URL into the selected element. There are also methods for sending GET or POST requests, and receiving the results. We will examine these methods in more depth while implementing Ajax features in our project. What Next? This wraps up our quick introduction to jQuery. The information provided in this section will be enough to continue with this article, and once you finish the article, you will be able to implement many interesting Ajax features on your own. But please keep in mind that this jQuery introduction is only the tip of the iceberg. If you want a comprehensive treatment of the jQuery framework, I highly recommend the book "Learning jQuery" from Packt Publishing, as it covers jQuery in much more detail. You can find out more about the book at: http://www.packtpub.com/jQuery Implementing Live Searching of Bookmarks We will start introducing Ajax into our application by implementing live searching. The idea behind this feature is simple: when the user types a few keywords into a text field and clicks search, a script works behind the scenes to fetch search results and present them on the same page. The search page does not reload, thus saving bandwidth, and providing a better and more responsive user experience. Before we start implementing this, we need to keep in mind an important rule while working with Ajax: write your application so that it works without Ajax, and then introduce Ajax to it. If you do so, you ensure that everyone will be able to use your application, including users who don't have JavaScript enabled and those who use browsers without Ajax support. Implementing Searching So before we work with Ajax, let's write a simple view that searches bookmarks by title. First of all, we need to create a search form, so open bookmarks/forms.py and add the following class to it: class SearchForm(forms.Form): query = forms.CharField( label='Enter a keyword to search for', widget=forms.TextInput(attrs={'size': 32})) As you can see, it's a pretty straightforward form class with only one text field. This field will be used by the user to enter search keywords. Next, let's create a view for searching. Open bookmarks/views.py and enter the following code into it: def search_page(request): form = SearchForm() bookmarks = [] show_results = False if request.GET.has_key('query'): show_results = True query = request.GET['query'].strip() if query: form = SearchForm({'query' : query}) bookmarks = Bookmark.objects.filter (title__icontains=query)[:10] variables = RequestContext(request, { 'form': form, 'bookmarks': bookmarks, 'show_results': show_results, 'show_tags': True, 'show_user': True })return render_to_response('search.html', variables) Apart from a couple of method calls, the view should be very easy to understand. We first initialize three variables, form which holds the search form, bookmarks which holds the bookmarks that we will display in the search results, and show_results which is a Boolean flag. We use this flag to distinguish between two cases: The search page was requested without a search query. In this case, we shouldn't display any search results, not even a "No bookmarks found" message. The search page was requested with a search query. In this case, we display the search results, or a "No bookmarks found" message if the query does not match any bookmarks. We need the show_results flag because the bookmarks variable alone is not enough to distinguish between the above two cases. bookmarks will empty when the search page is requested without a query, and it will also be empty when the query does not match any bookmarks. Next, we check whether a query was sent by calling the has_key method on the request.GET dictionary: if request.GET.has_key('query'): show_results = True query = request.GET['query'].strip() if query: form = SearchForm({'query' : query}) bookmarks = Bookmark.objects.filter(title__icontains=query)[:10] We use GET instead of POST here because the search form does not create or change data; it merely queries the database, and the general rule is to use GET with forms that query the database, and POST with forms that create, change or delete records from the database. If a query was submitted by the user, we set show_results to True and call strip() on the query string to ensure that it contains non-whitespace characters before we proceed with searching. If this is indeed the case, we bind the form to the query and retrieve a list of bookmarks that contain the query in their title. Searching is done by using a method called filter in Bookmark.objects. This is the first time that we have used this method; you can think of it as the equivalent of a SELECT statements in Django models. It receives the search criteria in its arguments and returns search results. The name of each argument must adhere to the following naming convention: field__operator Note that field and operator are separated by two underscores: field is the name of the field that we want to search by and operator is the lookup method that we want to use. Here is a list of the commonly-used operators: exact: The value of the argument is an exact match of the field. contains: The field contains the value of the argument. startswith: The field starts with the value of the argument. lt: The field is less than the value of the argument. gt: The field is greater than the value of the argument. Also, there are case-insensitive versions of the first three operators: iexact, icontains and istartswith. After this explanation of the filter method, let's get back to our search view. We use the icontains operator to get a list of bookmarks that match the query and retrieve the first ten items using Python's list slicing syntax. Finally we pass all the variables to a template called search.html to render the search page. Now create the search.html template in the templates directory with the following content: {% extends "base.html" %}{% block title %}Search Bookmarks{% endblock %}{% block head %}Search Bookmarks{% endblock %}{% block content %}<form id="search-form" method="get" action="."> {{ form.as_p }} <input type="submit" value="search" /></form><div id="search-results"> {% if show_results %} {% include 'bookmark_list.html' %} {% endif %}</div>{% endblock %} The template consists of familiar aspects that we have used before. We build the results list by including the bookmark_list.html like we did when building the user and tag pages. We gave the search form an ID, and rendered the search results in a div identified by another ID so that we can interact with them using JavaScript later. Notice how many times the include template tag saved us from writing additional code? It also lets us modify the look of the bookmarks list by editing a single file. This Django template feature is indeed very helpful in organizing and managing templates. Before you test the new view, add an entry for it in urls.py: urlpatterns = patterns('', # Browsing (r'^$', main_page), (r'^user/(w+)/$', user_page), (r'^tag/([^s]+)/$', tag_page), (r'^tag/$', tag_cloud_page), (r'^search/$', search_page),) Now test the search view by navigating to http://127.0.0.1:8000/search/ and experiment with it. You can also add a link to it in the navigation menu if you want; edit templates/base.html and add the highlighted code: <div id="nav"> <a href="/">home</a> | {% if user.is_authenticated %} <a href="/save/">submit</a> | <a href="/search/">search</a> | <a href="/user/{{ user.username }}/"> {{ user.username }}</a> | <a href="/logout/">logout</a> {% else %} <a href="/login/">login</a> | <a href="/register/">register</a> {% endif %}</div> We now have a functional (albeit very basic) search page. Thanks to our modular code, the task will turn out to be much simpler than it may seem. Implementing Live Searching To implement live searching, we need to do two things: Intercept and handle the event of submitting the search form. This can be done using the submit() method of jQuery. Use Ajax to load the search results in the back scenes, and insert them into the page. This can be done using the load() method of jQuery as we will see next. jQuery offers a method called load() that retrieves a page from the server and inserts its contents into the selected element. In its simplest form, the function takes the URL of the remote page to be loaded as a parameter. First of all, let's modify our search view a little so that it only returns search results without the rest of the search page when it receives an additional GET variable called ajax. We do so to enable JavaScript code on the client-side to easily retrieve search results without the rest of the search page HTML. This can be done by simply using the bookmark_list.html template instead of search.html when request.GET contains the key ajax. Open bookmarks/views.py and modify search_page (towards the end) so that it becomes as follows: def search_page(request): [...] variables = RequestContext(request, { 'form': form, 'bookmarks': bookmarks, 'show_results': show_results, 'show_tags': True, 'show_user': True }) if request.GET.has_key('ajax'): return render_to_response('bookmark_list.html', variables) else: return render_to_response('search.html', variables) Next, create a file called search.js in the site_media directory and link it to templates/search.html like this: {% extends "base.html" %}{% block external %} <script type="text/javascript" src="/site_media/search.js"> </script>{% endblock %}{% block title %}Search Bookmarks{% endblock %}{% block head %}Search Bookmarks{% endblock %}[...] Now for the fun part! Let's create a function that loads search results and inserts them into the corresponding div. Write the following code into site_media/search.js: function search_submit() { var query = $("#id_query").val(); $("#search-results").load( "/search/?ajax&query=" + encodeURIComponent(query) ); return false;} Let's go through this function line by line: The function first gets the query string from the text field using the val() method. We use the load() method to get search results from the search_page view, and insert the search results into the #search-results div. The request URL is constructed by first calling encodeURIComponent on query, which works exactly like the urlencode filter we used in Django templates. Calling this function is important to ensure that the constructed URL remains valid even if the user enters special characters into the text field such as &. After escaping query, we concatenate it with /search/?ajax&query=. This URL invokes the search_page view and passes the GET variables ajax and query to it. The view returns search results, and the load() method in turn loads the results into the #search-results div. We return false from the function to tell the browser not to submit the form after calling our handler. If we don't return false in the function, the browser will continue to submit the form as usual, and we don't want that. One little detail remains; where and when to attach search_submit to the submit event of the search form? A rule of a thumb when writing JavaScript is that we cannot manipulate elements in the document tree before the document finishes loading. Therefore, our function must be invoked as soon as the search page is loaded. Fortunately for us, jQuery provides a method to execute a function when the HTML document is loaded. Let's utilize it by appending the following code to site_media/search.js: $(document).ready(function () { $("#search-form").submit(search_submit);}); $(document) selects the document element of the current page. Notice that there are no quotations around document; it's a variable provided by the browser, not a string. ready() is a method that takes a function and executes it as soon as the selected element finishes loading. So in effect, we are telling jQuery to execute the passed function as soon as the HTML document is loaded. We pass an anonymous function to the ready() method; this function simply binds search_submit to the submit event of the form #search-form. That's it. We've implemented live searching with less than fifteen lines of code. To test the new functionality, navigate to http://127.0.0.1:8000/search/, submit queries, and notice how the results are displayed without reloading the page: The information covered in this section can be applied to any form that needs to be processed in the back scenes without reloading the page. You can, for example, create a comment form with a preview button that loads the preview in the same page without reloading. In the next section, we will enhance the user page to let users edit their bookmarks in place, without navigating away from the user page. Editing Bookmarks in Place Editing of posted content is a very common task in web sites. It's usually implemented by offering an edit link next to content. When clicked, this link takes the user to a form located on another page where content can be edited. When the user submits the form, they are redirected back to the content page. Imagine, on the other hand, that you could edit content without navigating away from the content page. When you click edit, the content is replaced with a form. When you submit the form, it disappears and the updated content appears in its place. Everything happens on the same page; edit form rendering and submission are done using JavaScript and Ajax. Wouldn't such a workflow be more intuitive and responsive? The technique described above is called in-place editing. It is now finding its way into web applications and becoming more common. We will implement this feature in our application by letting the user edit their bookmarks in place on the user page. Since our application doesn't support the editing of bookmarks yet, we will implement this first, and then modify the editing procedure to work in place. Implementing Bookmark Editing We already have most of the parts that are needed to implement bookmark editing. This was easy to do thanks to the get_or_create method provided by data models. This little detail greatly simplifies the implementation of bookmark editing. Here is what we need to do: We pass the URL of the bookmark that we want to edit as a GET variable named url to the bookmark_save_page view. We modify bookmark_save_page so that it populates the fields of the bookmark form if it receives the GET variable. The form is populated with the data of the bookmark that corresponds to the passed URL. When the populated form is submitted, the bookmark will be updated as we explained earlier, because it will look like the user submitted the same URL another time. Before we implement the technique described above, let's reduce the size of bookmark_save_page by moving the part that saves a bookmark to a separate function. We will call this function _bookmark_save. The underscore at the beginning of the name tells Python not to import this function when the views module is imported. The function expects a request and a valid form object as parameters; it saves a bookmark out of the form data, and returns this bookmark. Open bookmarks/views.py and create the following function; you can cut and paste the code from bookmark_save_page if you like, as we are not making any changes to it except for the return statement at the end. def _bookmark_save(request, form): # Create or get link. link, dummy = Link.objects.get_or_create(url=form.clean_data['url']) # Create or get bookmark. bookmark, created = Bookmark.objects.get_or_create( user=request.user, link=link ) # Update bookmark title. bookmark.title = form.clean_data['title'] # If the bookmark is being updated, clear old tag list. if not created: bookmark.tag_set.clear() # Create new tag list. tag_names = form.clean_data['tags'].split() for tag_name in tag_names: tag, dummy = Tag.objects.get_or_create(name=tag_name) bookmark.tag_set.add(tag)# Save bookmark to database and return it.bookmark.save()return bookmark Now in the same file, replace the code that you removed from bookmark_save_page with a call to _bookmark_save: @login_requireddef bookmark_save_page(request): if request.method == 'POST': form = BookmarkSaveForm(request.POST) if form.is_valid(): bookmark = _bookmark_save(request, form) return HttpResponseRedirect( '/user/%s/' % request.user.username )else: form = BookmarkSaveForm()variables = RequestContext(request, { 'form': form})return render_to_response('bookmark_save.html', variables) The current logic in bookmark_save_page works like this: if there is POST data:Validate and save bookmark.Redirect to user page.else:Create an empty form.Render page. To implement bookmark editing, we need to slightly modify the logic as follows: if there is POST data: Validate and save bookmark. Redirect to user page.else if there is a URL in GET data: Create a form an populate it with the URL's bookmark.else: Create an empty form.Render page. Let's translate the above pseudo code into Python. Modify bookmark_save_page in bookmarks/views.py so that it looks like the following (new code is highlighted): from django.core.exceptions import ObjectDoesNotExist@login_requireddef bookmark_save_page(request): if request.method == 'POST': form = BookmarkSaveForm(request.POST) if form.is_valid(): bookmark = _bookmark_save(request, form) return HttpResponseRedirect( '/user/%s/' % request.user.username ) elif request.GET.has_key('url'): url = request.GET['url'] title = '' tags = '' try: link = Link.objects.get(url=url) bookmark = Bookmark.objects.get( link=link, user=request.user ) title = bookmark.title tags = ' '.join( tag.name for tag in bookmark.tag_set.all() ) except ObjectDoesNotExist: pass form = BookmarkSaveForm({ 'url': url, 'title': title, 'tags': tags }) else: form = BookmarkSaveForm() variables = RequestContext(request, { 'form': form }) return render_to_response('bookmark_save.html', variables) This new section of the code first checks whether a GET variable called url exists. If this is the case, it loads the corresponding Link and Bookmark objects of this URL, and binds all the data to a bookmark saving form. You may wonder why we load the Link and Bookmark objects in a try-except construct that silently ignores exceptions. Indeed, it's perfectly valid to raise an Http404 exception if no bookmark was found for the requested URL. But our code chooses to only populate the URL field in this situation, leaving the title and tags fields empty.
Read more
  • 0
  • 0
  • 11304

article-image-xen-virtualization-work-mysql-server-ruby-rails-and-subversion
Packt
22 Oct 2009
7 min read
Save for later

Xen Virtualization: Work with MySQL Server, Ruby on Rails, and Subversion

Packt
22 Oct 2009
7 min read
Base Appliance Image We will use an Ubuntu Feisty domain image as the base image for creating these appliances. This image should be made as sparse and small as possible, and free of any cruft. A completely stripped down version of Linux with only the bare necessities would be a great start. In this case, we will not need any graphical desktop environments, so we can completely eliminate software packages like the X11 and any window manager like Gnome or KDE. Once we have a base image, we can back it up and then start using it for creating Xen appliances. In this article we will use an Ubuntu Feisty domain as the base image. Once this domain image is ready we are going to update it and clean it up a little bit so it can be our base. Edit the sources list for apt and add in other repositories that we will need to get software packages we will need when creating these appliances. Update your list of software. This will connect to the apt repositories and get the latest list of packages. We will do the actual update in the next step. Upgrade the distribution to ensure that you have the latest versions of all the packages. Automatically clean the image so all unused packages are removed. This will ensure that the image stays free of cruft.   Now we have the base appliance image ready, we will use it to create some Xen appliances. You can make a backup of the original base image and every time you create an appliance you can use a copy as the starting point or template. The images are nothing but domU images, which are customized for running only specific applications. You start them up and run them like ay other Xen guest domains. MySQL Database Server MySQL is one of the most popular open-source databases in the world. It is a key component of the LAMP architecture – (Linux Apache MySQL and PHP). It is also very easy to get started with MySQL and is one of the key factors driving its adoption across the enterprise. In this section we will create a Xen appliance that will run a MySQL database server and also provide the ability to automatically backup the database on a given schedule. Time for Action – Create our first Xen appliance We will use our base Ubuntu Feisty domain image, and add MySQL and other needed software to it. Please ensure that you have updated your base image to the latest versions of the repositories and software packages before creating this appliance. Install mysql-server using apt. Once it is installed, Ubuntu will automatically start the database server. So before we make our other changes, stop MySQL. Edit the /etc/mysql/my.cnf and comment out the line for the bind-address parameter. This will ensure that MySQL will accept connections from external machines and not just the localhost. Start a mysql console session to test that everything is installed and working correctly. Next we will install the utility for doing the automated backups. In order to do that we will first need to install the wget utility for transferring files. This is not a part of the base Ubuntu Feisty installation. Download the automysqlbackup script from the website. Copy this script to wherever you like, maybe /opt. Create a link to this location so it’s easy to do future updates. # cp automysqlbackup.sh.2.5 /opt# ln -s automysqlbackup.sh.2.5 automysqlbackup.sh Edit the script and modify the parameters at the top of the script to match your environment. Here are the changes to be made in our case. # Username to access the MySQL server e.g. dbuserUSERNAME=pchaganti# Username to access the MySQL server e.g. passwordPASSWORD=password# Host name (or IP address) of MySQL server e.g localhostDBHOST=localhost# List of DBNAMES for Daily/Weekly Backup e.g. "DB1 DB2 DB3"DBNAMES="all"# Backup directory location e.g /backupsBACKUPDIR="/var/backup/mysql"# Mail setupMAILCONTENT="quiet" Schedule this backup script to be run daily by creating a crontab entry for it, in the following format. 45 5 * * * root  /opt/automysqlbackup.sh >/dev/null 2>&1 Now we have a MySQL database server with automatic daily backups as a nice reusable Xen appliance. What just happened? We created our first Xen appliance! It is running the open-source MySQL database server along with an automated backup of the database as per the given schedule. This image is essentially a domU image and it can be uploaded along with its configuration file to a repository somewhere, and can be used by anyone in the enterprise or elsewhere with their Xen server. You can either start up the domain manually as and when you need it or set it up to boot automatically when your xend server starts. Ruby on Rails Appliance Ruby on Rails is one of the hottest web development frameworks around. It is simple to use and you can use all the expressive power of the Ruby language. It provides a great feature set and has really put the Ruby language on the map. Ruby on Rails is gaining rapid adoption across the IT landscape and for a wide variety of web applications. In this section, we are going to create a Rails appliance that contains Ruby, Rails, and the Mongrel cluster for serving the Rails application and nginx web server for the static content. This appliance gives you a great starting point for your explorations into the world of Ruby on Rails and can be an excellent learning resource. Time for Action – Rails on Xen We will use our base Ubuntu Feisty domain image and add Rails and other needed software to it. Please ensure that you have updated your base image to the latest versions of the repositories and software packages before creating this appliance. Install the packages required for compiling software on an Ubuntu system. This is required as we will be compiling some native extensions. Once the image is done, you can always remove this package if you want to save space. Install Ruby and other packages that are needed for it. Download the RubyGems package from RubyForge. We will use this to install any Ruby libraries or packages that we will need, including Rails. Now install Rails. The first time when you run this command on a clean Ubuntu Feisty system, you will get the following error. Ignore this error and just run the command once again and it will work fine. This will install Rails and all of its dependencies. Create a new Rails application. This will create everything needed in a directory named xenbook. $ rails xenbook  Change into the directory of the application that we created in the previous step and start the server up. This will start Ruby’s built-in web server, webrick by default. Launch a web browser and navigate to the web page for our xenbook application. We have everything working for a simple Rails install. However, we are using webrick, which is a bit slow. So let’s install the Mongrel server and use it with Rails. We will actually install mongrel_cluster that will let us use a cluster of Mongrel processes for serving up our Rails application.
Read more
  • 0
  • 0
  • 2985
Modal Close icon
Modal Close icon