Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-performance-enhancements-aspnet
Packt
26 Jul 2013
40 min read
Save for later

Performance enhancements to ASP.NET

Packt
26 Jul 2013
40 min read
ASP.NET performance Performance is one of the primary goals for any system. For a server, the throughput /time actually specifies the performance of the hardware or software in the system. It is important to increase performance and decrease the amount of hardware used for the throughput. There must be a balance between the two. Performance is one of the key elements of web development. In the last phase of ASP.NET 4.5, performance was one of the key concerns for Microsoft. They made a few major changes to the ASP.NET system to make it more performant. Performance comes directly, starting from the CPU utilization all the way back to the actual code you write. Each CPU cycle you consume for producing your response will affect performance. Consuming a large number of CPU cycles will lead you to add more and more CPUs to avoid site unavailability. As we are moving more and more towards the cloud system, performance is directly related to the cost. Here, CPU cycles costs money. Hence to make a more cost effective system running on the cloud, unnecessary CPU cycles should always be avoided. .NET 4.5 addresses the problem to its core to support background GC. The background GC for the server introduces support for concurrent collection without blocking threads; hence the performance of the site is not compromised because of garbage collection as well. The multicore JIT in addition improves the start-up time of pages without additional work. By the way, some of the improvements in technology can be really tangible to developers as well as end users. They can be categorized as follows. CPU and JIT improvements ASP.NET feature improvements The first category is generally intangible while the second case is tangible. The CPU and JIT improvements, as we have already discussed, are actually related to server performance. JIT compilations are not tangible to the developers which means they will automatically work on the system rather than any code change while the second category is actually related to code. We will focus here mainly on the tangible improvements in this recipe. Getting ready To get started, let us start Visual Studio 2012 and create an ASP.NET project. If you are opening the project for the first time, you can choose the ASP.NET Web Forms Application project template. Visual Studio 2012 comes with a cool template which virtually creates the layout of a blank site. Just create the project and run it and you will be presented with a blank site with all the default behaviors you need. This is done without writing a single line of code. Now, if you look into Solution Explorer, the project is separated into folders, each representing its identification. For instance, the Scripts folder includes all the JavaScript associated with the site. You can also see the Themes folder in Content, which includes the CSS files. Generally, for production-level sites, we have large numbers of JavaScript and CSS files that are sometimes very big and they download to the client browser when the site is initially loaded. We specify the file path using the script or link path. If you are familiar with web clients you will know that, the websites request these files in a separate request after getting the HTTP response for the page. As most browsers don't support parallel download, the download of each file adds up to the response. Even during the completion of each download there is a pause, which we call network latency. So, if you see the entire page response of a website, you will see that a large amount of response time is actually consumed by the download of these external files rather than the actual website response. Let us create a page on the website and add few JavaScript files and see the response time using Fiddler: The preceding screenshot shows how the browser requests the resources. Just notice, the first request is the actual request made by the client that takes half of a second, but the second half of that second is consumed by the requests made by the response from the server. The server responds with a number of CSS and JavaScript requests in the header, which have eventually been called to the same web server one by one. Sometimes, if the JavaScript is heavy, it takes a lot of time to load these individual files to the client which results in delay in response time for the web page. It is the same with images too. Even though external files are downloaded in separate streams, big images hurt the performance of the web page as well: Here you can see that the source of the file contains the call to a number of files that corresponds to each request. When the HTML is processed on the browser, it invokes each of these file requests one by one and replaces the document with the reference of those files. As I have already told you, making more and more resources reduces the performance of a page. This huge number of requests makes the website very slow. The screenshot depicts the actual number of requests, the bytes sent and received, and the performance in seconds. If you look at some big applications, the performance of the page is reduced by a lot more than this. To address this problem we take the following two approaches: Minimizing the size of JavaScript and CSS by removing the whitespaces, newlines, tab spaces, and so on, or omitting out the unnecessary content Bundling all the files into one file of the same MIME type to reduce the requests made by the browser ASP.NET addresses both of these problems and introduces a new feature that can both minimize the content of the JavaScript and CSS files as well as bundle all the JavaScript or CSS files together to produce one single file request from the site. To use this feature you need to first install the package. Open Visual Studio 2012, select View | Other Windows | Package Manager Console as shown in the following screenshot. Package Manager Console will open the PowerShell window for package management inside Visual Studio: Once the package manager is loaded, type the following command. Install-Package Microsoft.Web.Optimization This will load the optimizations inside Visual Studio. On the other hand, rather than opening Package Manager Console, you can also open Nuget package manager by right-clicking on the references folder of the project and select Add Library Package Reference. This will produce a nice dialog box to select and install the appropriate package. In this recipe, we are going to cover how to take the benefits of bundling and minification of website contents in .NET 4.5. How to do it... In order to move ahead with the recipe, we will use a blank web solution instead of the template web solution that I have created just now. To do this, start Visual Studio and select the ASP.NET Empty Web Application template. The project will be created without any pages but with a web.config file (a web.config file is similar to app.config but works on web environments). Add a new page to the project and name it as home.aspx. Leave it as it is, and go ahead by adding a folder to the solution and naming it as Resources. Inside resources, create two folders, one for JavaScript named js and another for stylesheets name css. Create a few JavaScript files inside js folder and a few CSS files inside the css folder. Once you finish the folder structure will look like below: Now let us add the files on the home page. Just drag-and-drop the js files one by one into the head section of the page. The page IDE will produce the appropriate tags for scripts and CSS automatically. Now run the project. You will see that the CSS and the JavaScript are appropriately loaded. To check, try using Fiddler. When you select the source of a page, you will see links that points to the JavaScript, CSS, or other resource files. These files are directly linked to the source and hence if we navigate to these files, it will show the raw content of the JavaScript. Open Fiddler and refresh the page keeping it open in Internet Explorer in the debug mode. You will see that the browser invokes four requests. Three of them are for external files and one for the actual HTML file. The Fiddler shows how the timeframe of the request is maintained. The first request being for the home.aspx file while the others are automatically invoked by the browser to get the js and css files. You can also take a note at the total size of the whole combined request for the page. Let's close the browser and remove references to the js and css files from the head tag, where you have dragged and added the following code to reference folders rather than individual files: <script src = "Resources/js"></script> <link rel="stylesheet" href="Resources/css" /> Open the Global.asax file (add if not already added) and write the following line in Application_Start: void Application_Start(object sender, EventArgs e) { //Adds the default behavior BundleTable.Bundles.EnableDefaultBundles(); } Once the line has been added, you can now run the project and see the output. If you now see the result in Fiddler, you will see all the files inside the scripts are clubbed into a single file and the whole file gets downloaded in a single request. If you have a large number of files, the bundling will show considerable performance gain for the web page. Bundling is not the only performance gain that we have achieved using Optimization. Press F5 to run the application and try to look into the actual file that has been downloaded as js and css. You will see that the bundle has been minified already by disregarding comments, blank spaces, new lines, and so on. Hence, the size of the bundles has also been reduced physically. You can also add your custom BundleTable entries. Generally, we add them inside the Application_Start section of the Global.asax file, like so: Bundle mybundle = new Bundle("~/mycustombundle", typeof(JsMinify)); mybundle.AddFile("~/Resources/Main.js"); mybundle.AddFile("~/Resources/Sub1.js"); mybundle.AddDirectory("/Resources/Files", "*.js", false); BundleTable.Bundles.Add(mybundle); The preceding code creates a new bundle for the application that can be referenced later on. We can use AddFile to add individual files to the Bundle or we can also use AddDirectory to specify a whole directory for a particular search pattern. The last argument for AddDirectory specifies whether it needs to search for a subdirectory or not. JsMinify is the default Rule processor for the JavaScript files. Similar to JsMinify is a class called CssMinfy that acts as a default rule for CSS minification. You can reference your custom bundle directly inside your page using the following directive: <script src = "mycustombundle" type="text/javascript" /> You will notice that the directive appropriately points to the custom bundle that has been created. How it works... Bundling and minification works with the introduction of the System.Web.Optimization namespace. BundleTable is a new class inside this namespace that keeps track of all the bundles that have been created in the solution. It maintains a list of all the Bundle objects, that is, list of JavaScript or CSS files, in a key-value pair collection. Once the request for a bundle is made, HttpRuntime dynamically combines the files and/or directories associated with the bundle into a single file response. Let us consider some other types that helps in transformation. BundleResponse: This class represents the response after the resources are bundled and minified. So BundleResponse keeps track of the actual response of the combined file. IBundleTransform: This type specifies the contract for transformation. Its main idea is to provide the transformation for a particular resource. JsMinfy or CssMinify are the default implementations of IBundleTransform. Bundle: The class represents a resource bundle with a list of files or directories. The IBundleTransform type specifies the rule for producing the BundleResponse class. To implement custom rules for a bundle, we need to implement this interface. public class MyCustomTransform : IBundleTransform { public void Process(BundleResponse bundleresponse) { // write logic to Bundle and minfy… } } Here, the BundleResponse class is the actual response stream where we need to write the minified output to. Basically, the application uses the default BundleHandler class to initiate the transform. BundleHandler is an IHttpHandler that uses ProcessRequest to get the response for the request from the browser. The process is summarized as follows: HttpRuntime calls the default BundleHandler.ProcessRequest method to handle the bundling and minification request initiated by the browser. ProcessRequest gets the appropriate bundle from the BundleTable class and calls Bundle.ProcessRequest. The Bundle.ProcessRequest method first retrieves the bundle's Url and invokes Bundle.GetBundleResponse. GetBundleResponse first performs a cache lookup. If there is no cache available, it calls GenerateBundleResponse. The GenerateBundleResponse method creates an instance of BundleResponse, sets the files to be processed in correct order, and finally invokes IBundleTransform.Process. The response is then written to BundleResponse from this method and the output is thrown back to the client. The preceding flow diagram summarizes how the transformation is handled by ASP.NET. The final call to IBundleTransform returns the response back to the browser. There's more... Now let's talk about some other options, or possibly some pieces of general information that are relevant to this task. How to configure the compilation of pages in ASP.NET websites Compilation also plays a very vital role in the performance of websites. As we have already mentioned, we have background GC available to the servers with .NET 4.5 releases, which means when GC starts collecting unreferenced objects, there will be no suspension of executing threads on the server. The GC can start collecting in the background. The support of multicore JIT will increase the performance of non-JITed files as well. By default, .NET 4.5 supports multicore JIT. If you want to disable this option, you can use the following code. <system.web> <compilation profileGuidedOptimizations="None" /> </system.web> This configuration will disable the support of spreading the JIT into multiple cores. The server enables a Prefetcher technology, similar to what Windows uses, to reduce the disk read cost of paging during application startup. The Prefetcher is enabled by default, you can also disable this using the following code: <system.web> <compilation enablePrefetchOptimization ="false" /> </system.web> This settings will disable the Prefetcher technology on the ASP.NET site. You can also configure your server to directly manipulate the amount of GC: <runtime> <performanceScenario value="HighDensityWebHosting" /> The preceding configuration will make the website a high density website. This will reduce the amount of memory consumed per session. What is unobtrusive validation Validation plays a very vital role for any application that employs user input. We generally use ASP.NET data validators to specify validation for a particular control. The validation forms the basis of any input. People use validator controls available in ASP.NET (which include RequiredFieldValidator, RangeValidator, and so on) to validate the controls when either a page is submitted or when the control loses its focus or on any event the validator is associated with. Validators being most popular server-side controls that handles client-side validation by producing an inline JavaScript block inside the actual page that specifies each validator. Let us take an instance: <asp:TextBox ID="Username" runat="server"></asp:TextBox> <asp:RequiredFieldValidator ErrorMessage="Username is required!" ControlToValidate="Username" runat="server"></asp:RequiredFieldValidator> <asp:RegularExpressionValidator ErrorMessage="Username can only contain letters!" ControlToValidate="Username" ValidationExpression="^[A-Za-z]+$" runat="server"></asp:RegularExpressionValidator> The validator handles both the client-side and server-side validations. When the preceding lines are rendered in the browser, it produces a mess of inline JavaScript. .NET 4.5 uses unobtrusive validation. That means the inline JavaScript is replaced by the data attributes in the HTML. This is a normal HTML-only code and hence performs better than the inline HTML and is also very understandable, neat, and clean. You can also turn off the default behavior of the application just by adding the line in Application_Start of the Global.asax file: void Application_Start(object sender, EventArgs e) { //Disable UnobtrusiveValidation application wide ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.None; } The preceding code will disable the feature for the application. Applying appSettings configuration key values Microsoft has implemented the ASP.NET web application engine in such a way that most of its configurations can be overridden by the developers while developing applications. There is a special configuration file named Machine.config that provides the default configuration of each of the config sections present for every application. web.config is specific to an application hosted on IIS. The IIS reads through the configuration of each directory to apply for the pages inside it. As configuring a web application is such a basic thing for any application, there is always a need to have a template for a specific set of configuration without rewriting the whole section inside web.config again. There are some specific requirements from the developers perspective that could be easily customizable without changing too much on the config.ASP.NET 4.5 introduces magic strings that could be used as configuration key values in the appSettings element that could give special meaning to the configuration. For instance, if you want the default built-in JavaScript encoding to encode & character, you might use the following: <appSettings> <add key="aspnet:JavaScriptDoNotEncodeAmpersand" value="false" /> </appSettings> This will ensure that & character is encoded as "u0026" which is the JavaScript-escaped form of that character. When the value is true, the default JavaScript string will not encode &. On the other hand, if you need to allow ScriptResource.axd to serve arbitrary static files other than JavaScript, you can use another magic appSettings key to handle this: <appSettings> <add key="aspnet:ScriptResourceAllowNonJsFiles" value="false" /> </appSettings> The configuration will ensure that ScriptResource.axd will not serve any file other than the .js extension even if the web page has a markup . Similar to this, you can also enable UnobtrusiveValidationMode on the website using a separate magic string on appSetting too: <appSettings> <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" /> </appSettings> This configuration will make the application to render HTML5 data-attributes for validators. There are a bunch of these appSettings key magic strings that you can use in your configuration to give special meaning to the web application. Refer to http://bit.ly/ASPNETMagicStrings for more information. DLL intern in ASP.NET servers Just like the reusability of string can be achieved using string intern tables, ASP.NET allows you to specify DLL intern that reduces the use of loading multiple DLLs into memory from different physical locations. The interning functionality introduced with ASP.NET reduces the RAM requirement and load time-even though the same DLL resides on multiple physical locations, they are loaded only once into the memory and the same memory is being shared by multiple processes. ASP.NET maintains symbolic links placed on the bin folder that map to a shared assembly. Sharing assemblies using a symbolic link requires a new tool named aspnet_intern.exe that lets you to create and manage the stored interned assemblies. To make sure that the assemblies are interned, we need to run the following code on the source directory: aspnet_inturn –mode exec –sourcedir "Temporary ASP.NET files" – interndir "c:assemblies" This code will put the shared assemblies placed inside assemblies directory interned to the temporary ASP.NET files. Thus, once a DLL is loaded into memory, it will be shared by other requests. How to work with statically-typed model binding in ASP.NET applications Binding is a concept that attaches the source with the target such that when something is modified on the source, it automatically reflects to the target. The concept of binding is not new in the .NET framework. It was there from the beginning. On the server-side controls, when we set DataSource, we generally don't expect DataSource to automatically produce the output to be rendered onto the actual HTML. We expect to call a DataBind method corresponding to the control. Something magical happens in the background that generates the actual HTML from DataSource and produces the output. DataSource expects a collection of items where each of the items produces single entry on the control. For instance, if we pass a collection as the data source of a grid, the data bind will enumerate the collection and each entry in the collection will create a row of DataGrid. To evaluate each property from within the individual element, we use DataBinder.Eval that uses reflection to evaluate the contextual property with actual data. Now we all know, DataBinder actually works on a string equivalent of the actual property, and you cannot get the error before you actually run the page. In case of model binding, the bound object generates the actual object. Model binding does have the information about the actual object for which the collection is made and can give you options such as IntelliSense or other advanced Visual Studio options to work with the item. Getting ready DataSource is a property of the Databound element that takes a collection and provides a mechanism to repeat its output replacing the contextual element of the collection with generated HTML. Each control generates HTML during the render phase of the ASP.NET page life cycle and returns the output to the client. The ASP.NET controls are built so elegantly that you can easily hook into its properties while the actual HTML is being created, and get the contextual controls that make up the HTML with the contextual data element as well. For a template control such as Repeater, each ItemTemplate property or the AlternateItemTemplate property exposes a data item in its callback when it is actually rendered. This is basically the contextual object of DataSource on the nth iteration. DataBinder.Eval is a special API that evaluates a property from any object using Reflection. It is totally a runtime evaluation and hence cannot determine any mistakes on designer during compile time. The contextual object also doesn't have any type-related information inherent inside the control. With ASP.NET 4.5, the DataBound controls expose the contextual object as generic types so that the contextual object is always strongly typed. The control exposes the ItemType property, which can also be used inside the HTML designer to specify the type of the contextual element. The object is determined automatically by the Visual Studio IDE and it produces proper IntelliSense and provides compile-time error checking on the type defined by the control. In this recipe we are going to see step by step how to create a control that is bound to a model and define the HTML using its inherent Item object. How to do it... Open Visual Studio and start an ASP.NET Web Application project. Create a class called Customer to actually implement the model. For simplicity, we are just using a class as our model: public class Customer { public string CustomerId { get; set; } public string Name { get; set; } } The Customer class has two properties, one that holds the identifier of the customer and another the name of the customer. Now let us add an ASPX file and add a Repeater control. The Repeater control has a property called ModelType that needs the actual logical path of the model class. Here we pass the customer. Once ModelType is set for the Repeater control, you can directly use the contextual object inside ItemTemplate just by specifying it with the : Item syntax: <asp:Repeater runat="server" ID="rptCustomers" ItemType="SampleBinding.Customer"> <ItemTemplate> <span><%# :Item.Name %></span> </ItemTemplate> </asp:Repeater> Here in this Repeater control we have directly accessed the Name property from the Customer class. So here if we specify a list of Customer values to its data source, it will bind the contextual objects appropriately. The ItemType property is available to all DataBound controls. The Databound controls in ASP.NET 4.5 also support CRUD operations. The controls such as Gridview, FormView, and DetailsView expose properties to specify SelectMethod, InsertMethod, UpdateMethod, or DeleteMethod. These methods allow you to pass proper methods that in turn allow you to specify DML statements. Add a new page called Details.aspx and configure it as follows: <asp:DetailsView SelectMethod="dvDepartments_GetItem" ID="dvDepartments" UpdateMethod="dvDepartments_ UpdateItem" runat="server" InsertMethod="dvDepartments_ InsertItem" DeleteMethod="dvDepartments_DeleteItem" ModelType="ModelBindingSample.ModelDepartment" AutoGenerateInsertB utton="true"> </asp:DetailsView> Here in the preceding code, you can see that I have specified all the DML methods. The code behind will have all the methods and you need to properly specify the methods for each operation. How it works... Every collection control loops through the Datasource control and renders the output. The Bindable controls support collection to be passed to it, so that it can make a template of itself by individually running the same code over and over again with a contextual object passed for an index. The contextual element is present during the phase of rendering the HTML. ASP.NET 4.5 comes with the feature that allows you to define the type of an individual item of the collection such that the template forces this conversion, and the contextual item is made available to the template. In other words, what we have been doing with Eval before, can now be done easily using the Item contextual object, which is of same type as we define in the ItemType property. The designer enumerates properties into an IntelliSense menu just like a C# code window to write code easier. Each databound control in ASP.NET 4.5 allows CRUD operations. For every CRUD operation there is a specific event handler that can be configured to handle operations defined inside the control. You should remember that after each of these operations, the control actually calls DataBind again so that the data gets refreshed. There's more... ModelBinding is not the only thing that is important. Let us discuss some of the other important concepts deemed fit to this category. ModelBinding with filter operations ModelBinding in ASP.NET 4.5 has been enhanced pretty much to support most of the operations that we regularly need with our ASP.NET pages. Among the interesting features is the support of filters in selection of control. Let us use DetailsView to introduce this feature: <asp:DropDownList ID="ddlDepartmentNames" runat="server" ItemType="ModelBindingSample.ModelDepartment" AutoPostBack="true" DataValueField="DepartmentId" DataTextField="DepartmentName" SelectMethod="GetDepartments"> </asp:DropDownList> <asp:DetailsView SelectMethod="dvDepartments_GetItems" ID="dvDepartments" UpdateMethod="dvDepartments_UpdateItem" runat="server" InsertMethod="dvDepartments_InsertItem" DeleteMethod="dvDepartments_DeleteItem" ItemType="ModelBindingSample.ModelCustomer" AutoGenerateIn sertButton="true"> </asp:DetailsView> Here you can see the DropDownList control calls Getdepartments to generate the list of departments available. The DetailsView control on the other hand uses the ModelCustomer class to generate the customer list. SelectMethod allows you to bind the control with the data. Now to get the filter out of SelectMethod we use the following code: public IQueryable<ModelCustomer> dvDepartments_GetItems([Control("ddlD epartmentNames")]string deptid) { // get customers for a specific id } This method will be automatically called when the drop-down list changes its value. The departmentid of the selected DropDownItem control is automatically passed into the method and the result is bound to DetailsView automatically. Remember, the dvDepartments_GetItems method always passes a Nullable parameter. So, if departmentid is declared as integer, it would have been passed as int? rather than int. The attribute on the argument specifies the control, which defines the value for the query element. You need to pass IEnumerable (IQueryable in our case) of the items to be bound to the control. You can also specify a filter using Querystring. You can use the following code: public IQueryable<Customer> GetCustomers([QueryString]string departmentid) { return null; }   This code will take departmentid from the query string and load the DataBound control instead of the control specified within the page. Introduction to HTML5 and CSS3 in ASP.NET applications Web is the media that runs over the Internet. It's a service that has already has us in its grasp. Literally, if you think of the Web, the first thing that can come into your mind is everything about HTML, CSS, and JavaScript. The browsers are the user agents that are used to communicate with the Web. The Web has been there for almost a decade and is used mostly to serve information about business, communities, social networks, and virtually everything that you can think of. For such a long period of time, users primarily use websites to see text-based content with minimum UI experiences and texts that can easily be consumed by search engines. In those websites, all that the browsers do is send a request for a page and the server serves the client with the appropriate page which is later rendered on the browser. But with the introduction to modern HTMLs, websites are gradually adopting interactivity in terms of CSS, AJAX, iFrame, or are even using sandboxed applications with the use of Silverlight, Flash, and so on. Silverlight and Adobe AIR (Flash) are specifically likely to be used when the requirement is great interactivity and rich clients. They totally look like desktop applications and interact with the user as much as they can. But the problems with a sandboxed application are that they are very slow and need every browser to install the appropriate plugin before they can actually navigate to the application. They are heavyweight and are not rendered by the browser engine. Even though they are so popular these days, most of the development still employs the traditional approach of HTML and CSS. Most businesses cannot afford the long loading waits or even as we move along to the lines of devices, most of these do not support them. The long term user requirements made it important to take the traditional HTML and CSS further, ornamenting it in such a way that these ongoing requirements could easily be solved using traditional code. The popularity of the ASP.NET technology also points to the popularity of HTML. Even though we are dealing with server-side controls (in case of ASP.NET applications), internally everything renders HTML to the browser. HTML5, which was introduced by W3C and drafted in June 2004, is going to be standardized in 2014 making most of the things that need desktop or sandboxed plugins easily carried out using HTML, CSS, and JavaScript. The long term requirement to have offline web, data storage, hardware access, or even working with graphics and multimedia is easily possible with the help of the HTML5 technology. So basically what we had to rely on (the sandbox browser plugins) is now going to be standardized. In this recipe, we are going to cover some of the interesting HTML5 features that need special attention. Getting ready HTML5 does not need the installation of any special SDK to be used. Most of the current browsers already support HTML5 and all the new browsers are going to support most of these features. The official logo of HTML5 has been considered as follows. HTML5 has introduced a lot of new advanced features but yet it also tries to simplify things that we commonly don't need to know but often need to remember in order to write code. For instance, the DocType element of an HTML5 document has been simplified to the following one line: <!DOCTYPE html> So, for an HTML5 document, the document type that specifies the page is simply HTML. Similar to DocType, the character set for the page is also defined in very simple terms. <meta charset="utf-8" /> The character set can be of any type. Here we specified the document to be UTF – 8. You do not need to specify the http-equiv attribute or content to define charset for the page in an HTML5 document according to the specification. Let us now jot down some of the interesting HTML5 items that we are going to take on in this recipe. Semantic tags, better markups, descriptive link relations, micro-data elements, new form types and field types, CSS enhancements and JavaScript enhancements. Not all browsers presently support every feature defined in HTML5. There are Modernizr scripts that can help as cross-browser polyfills for all browsers. You can read more information about it here. How to do it... The HTML5 syntax has been adorned with a lot of important tags which include header, nav, aside, figure, and footer syntaxes that help in defining better semantic meaning of the document: <body> <header> <hgroup> <h1>Page title</h1> <h2>Page subtitle</h2> </hgroup> </header> <nav> <ul> Specify navigation </ul> </nav> <section> <article> <header> <h1>Title</h1> </header> <section> Content for the section </section> </article> <article> <aside> Releated links </aside> <figure> <img src = "logo.jpg"/> <figcaption>Special HTML5 Logo</figcaption> </figure> <footer> Copyright © <time datetime="2010-11-08">2010</time>. </footer> </body> By reading the document, it clearly identifies the semantic meaning of the document. The header tag specifies the header information about the page. The nav tag defines the navigation panel. The Section tag is defined by articles and besides them, there are links. The img tag is adorned with the Figure tag and finally, the footer information is defined under the footer tag. A diagrammatic representation of the layout is shown as follows. The vocabulary of the page that has been previously defined by div and CSS classes are now maintained by the HTML itself and the whole document forms a meaning to the reader. HTML5 not only improves the semantic meaning of the document, it also adds new markup. For instance, take a look at the following code: <input list="options" type="text"/> <datalist id="options"> <option value="Abhishek"/> <option value="Abhijit"/> <option value="Abhik"/> </datalist> datalist specifies the autocomplete list for a control. A datalist item automatically pops up a menu while we type inside a textbox. The input tag specifies the list for autocomplete using the list attribute. Now if you start typing on the textbox, it specifies a list of items automatically. <details> <summary>HTML 5</summary> This is a sliding panel that comes when the HTML5 header is clicked </details> The preceding markup specifies a sliding panel container. We used to specify these using JavaScript, but now HTML5 comes with controls that handle these panels automatically. HTML5 comes with a progress bar. It supports the progress and meter tags that define the progress bar inside an HTML document: <meter min="0" max="100" low="40" high="90" optimum="100" value="91">A+</meter> <progress value="75" max="100">3/4 complete</progress> The progress shows 75 percent filled in and the meter shows a value of 91. HTML5 added a whole lot of new attributes to specify aria attributes and microdata for a block. For instance, consider the following code: <div itemscope itemtype="http://example.org/band"> <ul id="tv" role="tree" tabindex="0" aria-labelledby="node1"> <li role="treeitem" tabindex="-1" aria-expanded="true">Inside Node1</li> </li> </ul> Here, Itemscope defines the microdata and ul defines a tree with aria attributes. These data are helpful for different analyzers or even for automated tools or search engines about the document. There are new Form types that have been introduced with HTML5: <input type="email" value="some@email.com" /> <input type="date" min="2010-08-14" max="2011-08-14" value="2010-08-14"/> <input type="range" min="0" max="50" value="10" /> <input type="search" results="10" placeholder="Search..." /> <input type="tel" placeholder="(555) 555-5555" pattern="^(?d{3})?[-s]d{3}[-s]d{4}.*?$" /> <input type="color" placeholder="e.g. #bbbbbb" /> <input type="number" step="1" min="-5" max="10" value="0" /> These inputs types give a special meaning to the form. The preceding figure shows how the new controls are laid out when placed inside a HTML document. The controls are email, date, range, search, tel, color, and number respectively. HTML5 supports vector drawing over the document. We can use a canvas to draw 2D as well as 3D graphics over the HTML document: <script> var canvasContext = document.getElementById("canvas"). getContext("2d"); canvasContext.fillRect(250, 25, 150, 100); canvasContext.beginPath(); canvasContext.arc(450, 110, 100, Math.PI * 1/2, Math.PI * 3/2); canvasContext.lineWidth = 15; canvasContext.lineCap = 'round'; canvasContext.strokeStyle = 'rgba(255, 127, 0, 0.5)'; canvasContext.stroke(); </script> Consider the following diagram. The preceding code creates an arc on the canvas and a rectangle filled with the color black as shown in the diagram. The canvas gives us the options to draw any shape within it using simple JavaScript. As the world is moving towards multimedia, HTML5 introduces audio and video tags that allow us to run audio and video inside the browser. We do not need any third-party library or plugin to run audio or video inside a browser: <audio id="audio" src = "sound.mp3" controls></audio> <video id="video" src = "movie.webm" autoplay controls></video> The audio tag runs the audio and the video tag runs the video inside the browser. When controls are specified, the player provides superior browser controls to the user. With CSS3 on the way, CSS has been improved greatly to enhance the HTML document styles. For instance, CSS constructs such as .row:nth-child(even) gives the programmer control to deal with a particular set of items on the document and the programmer gains more granular programmatic approach using CSS. How it works... HTML5 is the standardization to the web environments with W3C standards. The HTML5 specifications are still in the draft stage (a 900-page specification available at http://www.w3.org/html/wg/drafts/html/master/), but most modern browsers have already started supporting the features mentioned in the specifications. The standardization is due in 2014 and by then all browsers need to support HTML5 constructs. Moreover, with the evolution of smart devices, mobile browsers are also getting support for HTML5 syntaxes. Most smart devices such as Android, iPhone, or Windows Phone now support HTML5 browsers and the HTML that runs over big devices can still show the content on those small browsers. HTML5 improves the richness of the web applications and hence most people have already started shifting their websites to the future of the Web. There's more... HTML5 has introduced a lot of new enhancements which cannot be completed using one single recipe. Let us look into some more enhancements of HTML5, which are important to know. How to work with web workers in HTML5 Web workers are one of the most awaited features of the entire HTML5 specification. Generally, if we think of the current environment, it is actually turning towards multicore machines. Today, it's verbal that every computer has at least two cores installed in their machine. Browsers are well capable of producing multiple threads that can run in parallel in different cores. But programmatically, we cannot have the flexibility in JavaScript to run parallel tasks in different cores yet. Previously, developers used setTimeout, setInterval, or XMLHttprequst to actually create non-blocking calls. But these are not truly a concurrency. I mean, if you still put a long loop inside setTimeout, it will still hang the UI. Actually these works asynchronously take some of the UI threads time slices but they do not actually spawn a new thread to run the code. As the world is moving towards client-side, rich user interfaces, we are prone to develop codes that are capable of computation on the client side itself. So going through the line, it is important that the browsers support multiple cores to be used up while executing a JavaScript. Web workers are actually a JavaScript type that enable you to create multiple cores and run your JavaScript in a separate thread altogether, and communicate the UI thread using messages in a similar way as we do for other languages. Let's look into the code to see how it works. var worker = new Worker('task.js'); worker.onmessage = function(event) { alert(event.data); }; worker.postMessage('data'); Here we will load task.js from Worker.Worker is a type that invokes the code inside a JavaScript in a new thread. The start of the thread is called using postMessage on the worker type. Now we have already added a callback to the event onmessage such that when the JavaScript inside task.js invokes postMessage, this message is received by this callback. Inside task.js we wrote. self.onmessage = function(event) { // Do some CPU intensive work. self.postMessage("recv'd: " + event.data); }; Here after some CPU-intensive work, we use self.postMessage to send the data we received from the UI thread and the onmessage event handler gets executed with message received data. Working with Socket using HTML5 HTML5 supports full-duplex bidirectional sockets that run over the Web. The browsers are capable of invoking socket requests directly using HTML5. The important thing that you should note with sockets is that it sends only the data without the overload of HTTP headers and other HTTP elements that are associated with any requests. The bandwidth using sockets is dramatically reduced. To use sockets from the browsers, a new protocol has been specified by W3C as a part of the HTML5 specification. WebSocket is a new protocol that supports two-way communication between the client and the server in a single TCP channel. To start socket server, we are going to use node.js for server side. Install node.js on the server side using the installer available at http://nodejs.org/dist/v0.6.6/node-v0.6.6.msi. Once you have installed node.js, start a server implementation of the socket. var io = require('socket.io'); //Creates a HTTP Server var socket = io.listen(8124); //Bind the Connection Event //This is called during connection socket.sockets.on('connection',function(socket){ //This will be fired when data is received from client socket.on('message', function(msg){ console.log('Received from client ',msg); }); //Emit a message to client socket.emit('greet',{hello: 'world'}); //This will fire when the client has disconnected socket.on('disconnect', function(){ console.log('Server has disconnected'); }); }); In the preceding code, the server implementation has been made. The require('socket.io') code snippet specifies the include module header. socket.io provides all the APIs from node.js that are useful for socket implementation. The Connection event is fired on the server when any client connects with the server. We have used to listen at the port 8124 in the server. socket.emit specifies the emit statement or the response from the server when any message is received by it. Here during the greet event, we pass a JSON object to the client which has a property hello. And finally, the disconnect event is called when the client disconnects the socket. Now to run this client implementation, we need to create a HTML file. <html> <title>WebSocket Client Demo</title> <script src = "http://localhost:8124/socket.io/socket.io.js"></ script> <script> //Create a socket and connect to the server var socket = io.connect('http://localhost:8124/'); socket.on("connect",function(){ alert("Client has connected to the server"); }); socket.on('greet', function (data) { alert(data.hello); } ); </script </html> Here we connect the server at 8124 port. The connect event is invoked first. We call an alert method when the client connects to the server. Finally, we also use the greet event to pass data from the server to the client. Here, if we run both the server and the client, we will see two alerts; one when the connection is made and the other alert to greet. The greet message passes a JSON object that greets with world. The URL for the socket from the browser looks like so. [scheme] '://' [host] '/' [namespace] '/' [protocol version] '/' [transport id] '/' [session id] '/' ( '?' [query] ) Here, we see. Scheme: This can bear values such as http or https (for web sockets, the browser changes it to ws:// after the connection is established, it's an upgrade request) host: This is the host name of the socket server namespace: This is the Socket.IO namespace, the default being socket.io protocol version: The client support default is 1 transport id: This is for the different supported transports which includes WebSockets, xhr-polling, and so on session id: This is the web socket session's unique session ID for the client Getting GeoLocation from the browser using HTML5 As we are getting inclined more and more towards devices, browsers are trying to do their best to actually implement features to suit these needs. HTML5 introduces GeoLocation APIs to the browser that enable you to get the location of your position directly using JavaScript. In spite of it being very much primitive, browsers are capable of detecting the actual location of the user using either Wi-Fi, satellite, or other external sources if available. As a programmer, you just need to call the location API and everything is handled automatically by the browser. As geolocation bears sensitive information, it is important to ask the user for permission. Let's look at the following code. if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { var latLng = "{" + position.coords.latitude + "," + position.coords. longitude + "with accuracy: " + position.coords.accuracy; alert(latLng); }, errorHandler); } Here in the code we first detect whether the geolocation API is available to the current browser. If it is available, we can use getCurrentPosition to get the location of the current device and the accuracy of the position as well. We can also use navigator.geolocation.watchPosition to continue watching the device location at an interval when the device is moving from one place to another.   Resources for Article: Further resources on this subject: Planning for a successful integration .NET 4.5 Extension Methods on IQueryable Core .NET Recipes
Read more
  • 0
  • 1
  • 4760

article-image-article-adding-dialogs
Packt
26 Jul 2013
19 min read
Save for later

Adding Dialogs

Packt
26 Jul 2013
19 min read
(For more resources related to this topic, see here.) Applying effects to dialog components Out-of-the-box, the dialog widget allows developers to show animations when the dialog is opened, as well as hide animations, when closed. This animation is applied to the dialog as a whole. So, for example, if we were to specify that the show option is a fade animation, the entire dialog will fade into view for the user. Likewise, if the hide option was fade, the dialog would fade out of view instead of instantaneously disappearing. To liven up this show and hide behavior, we could operate on individual dialog components. That is, instead of applying show and hide effects to the dialog as a whole, we could apply them to the individual parts inside the widget, like the title bar and the button pane. How to do it... The dialog we're going to create here is just about as simple as they come in terms of content. That is, we're going to only specify some basic title and content strings for the dialog in the HTML. <div title="Dialog Title"> <p>Basic dialog content</p> </div> In order to turn this idea of animating individual dialog components into reality, we'll have to extend the dialog widget in a few places. In particular, we're going to animate the title bar, at the top of the widget, as well as the button pane near the bottom. Here is what the JavaScript code looks like: (function( $, undefined ) { $.widget( "ab.dialog", $.ui.dialog, { _create: function() { this._super(); var dialog = this.uiDialog; dialog.find( ".ui-dialog-titlebar" ).hide(); dialog.find( ".ui-dialog-buttonpane" ).hide(); }, open: function() { this._super(); var dialog = this.uiDialog; dialog.find( ".ui-dialog-titlebar" ).toggle( "fold", 500 ); dialog.find( ".ui-dialog-buttonpane" ).toggle( "fold", 500 ); }, close: function( event, isCallback ) { var self = this, dialog = this.uiDialog; if ( isCallback ) { this._super( event ); return; } dialog.find( ".ui-dialog-titlebar" ).toggle( "fold", 500 ); dialog.find( ".ui-dialog-buttonpane" ).toggle( "fold", 500, function(){ self.element.dialog( "close", event, true ); }); } }); })( jQuery ); $(function() { $( "div" ).dialog({ show: "fade", hide: "scale", buttons: { Cancel: function() { $( this ).dialog( "close" ); } } }); }); When you open the page, you'll see the individual dialog components fade into view, independent of the fade animation we've specified for the dialog as a whole. Once visible, the dialog should look something like this: You'll also notice that the scale effect isn't applied until the fade effect is applied to the title bar and button panes. How it works... This code is one of those exceptions to the rule where we're not providing a mechanism with which to turn off our new extended functionality. That is, we have hard-coded changes in our custom implementation of some dialog methods that cannot be turned off by supplying an option value. However, the exception is made in an effort to trade-off complexity for desired functionality. Chances are that this type of custom animation work would happen as part of a specific project requirement, and not as a generalized extension of the dialog widget capabilities. The first thing we change about the default dialog implementation is in the _create() method, where we hide the .ui-dialog-titlebar and .ui-dialog-buttonpane components. This is done after calling the _super() method, which is responsible for creating the basic dialog components. Even if the dialog is set to open automatically with the autoOpen option, the _create() method doesn't actually display it. So, we can hide the title bar and button pane without the user noticing it. The reason we've hidden the two components is because we would like to apply a display effect once the dialog opens. The next method, open(), that we're overriding does exactly that. It first calls the _super() method, which initiates the effect for displaying the dialog (in our case, we've told it to fade on display). We then use the fold effect on the title bar and on the button pane. You'll notice that we don't wait for any animations to complete before starting the next. The dialog display animation is started, followed by the title bar and the button pane. All three could be executing at the same time, potentially. The reason we've done it this way is to retain the correct layout of the dialog. The last method to override is the close() method. This introduces an interesting work-around we must use in order to get _super() to work in a callback. Even with the self variable in the enclosing scope, we have problems calling the _super() method inside the callback. So, we use the widget element and pretend like we're calling .dialog( "close" ) from outside of the widget. The isCallback argument tells the close() method to call _super(), and return. The reason we need a callback to begin with is that we don't actually want to execute the dialog hide animation until we've finished animating the button pane. Waiting for API data to load More often than not, the dialog widget needs to load data from an API. That is, not all dialogs are composed of static HTML. They need data from the API to construct some of the elements using API data, such as select element options. Loading data from the API and building the resultant elements isn't the issue; we do this all the time. The challenge comes when we try to perform these activities within the dialog context. We don't necessarily want to display the dialog until the data has been loaded from the API, and the UI components used to display them inside the dialog components have been built. Ideally, we would block the dialog from displaying until the components displayed by the dialog are ready. This is especially tricky with remote API functionally, where it is impossible to predict latency issues. Furthermore, the dialog may depend on more than one API call, each populating its own UI component in the dialog. Getting ready... To implement a solution for the API data problem, we'll need some basic HTML and CSS to define the dialog and its content. We'll have two empty select elements in the dialog. This is what the HTML looks like: <div id="dialog" title="Genres and Titles"> <div class="dialog-field"> <label for="genres">Genres:</label> <select id="genres"></select> <div class="ui-helper-clearfix"></div> </div> <div class="dialog-field"> <label for="titles">Titles:</label> <select id="titles"></select> <div class="ui-helper-clearfix"></div> </div> </div> And, this is the supporting CSS for the previous code: .dialog-field { margin: 5px; } .dialog-field label { font-weight: bold; font-size: 1.1em; float: left; } .dialog-field select { float: right; } How to do it... We'll give the dialog widget the ability to block while waiting on API requests by extending the widget with a new option. This option will allow us to pass in an array of deferred promises. A promise is an object used to track the state of an individual Ajax call. With a collection of promises, we're able to implement complex blocking behavior using simple code like this: (function( $, undefined ) { $.widget( "ab.dialog", $.ui.dialog, { options: { promises: [] }, open: function( isPromise ) { var $element = this.element, promises = this.options.promises; if ( promises.length > 0 && !isPromise ) { $.when.apply( $, promises ).then( function() { $element.dialog( "open", true ); }); } else { this._super(); } }, }); })( jQuery ); $(function() { var repos = $.ajax({ url: "https://api.github.com/repositories", dataType: "jsonp", success: function( resp ) { $.each( resp.data, function( i, v ) { $( "<option/>" ).html( v.name ) .appendTo( "#repos" ); }); }, }); var users = $.ajax({ url: "https://api.github.com/users", dataType: "jsonp", success: function( resp ) { $.each( resp.data, function( i, v ) { $( "<option/>" ).html( v.login ) .appendTo( "#users" ); }); } }); $( "#dialog" ).dialog({ width: 400, promises: [ repos.promise(), users.promise() ] }); }); Once the API data is returned, for both the calls, the dialog is displayed and should look something like this: How it works... Let's start by looking at the document ready handler where we're actually instantiating the dialog widget. The first two variables defined here, repos and users, are $.Deferred objects. These represent two API calls we're making to the GitHub API. The objective of these calls is to populate the #repos and the #users select elements, respectively. These select elements make up part of our #dialog content. The success option specified in each Ajax call is a callback that performs the work of creating the option elements, and placing them in the select element. Without customizing the dialog widget, these two API calls would work just fine. The dialog would open, and eventually, the options would appear in the select elements (after the dialog has already opened). You'll notice, however, that we're passing an array of deferred.promise() objects to the dialog. This is a new capability we've given to the dialog widget. A deferred object, simply put, allows developers to postpone the consequences of some action that might take a while to complete, such as an Ajax call. A promise is something we get from a deferred object that lets us compose some criteria that says when a complex sequence, such as making multiple Ajax calls, is complete. The custom promises option we've added to the dialog widget is used in our implementation of the open() method. It is here that we can make use of these promises. Essentially, we're making a transaction out of one or more promise objects passed to the dialog—once they've all completed or resolved to use the jQuery terminology, we can open the dialog. We do so by passing the array of promise objects to the $.when() function, which calls the open() method on the dialog. However, a complication arises here that we must deal with. We can't call _super() from within a callback function because the core widget machinery doesn't understand how to find the parent widget class. So, we have to pretend as though we're calling open() from outside of the widget. We do this by using self.element, and the additional isPromise parameter, instructing our custom open() implementation on how to behave. Using icons in the dialog title With some dialogs, depending on the nature of the application and the content of the dialog itself, it may be beneficial to place an icon beside the dialog title. This could be beneficial in the sense that it provides additional context to the user. For example, an edit dialog might have a pencil icon, whereas a user profile dialog might contain a person icon. Getting ready... To illustrate adding an icon to the title bar of the dialog widget, we'll use the following as our basic HTML: <div id="dialog" title="Edit"> <div> <label>Field 1:</label> <input type="text"/> </div> <div> <label>Field 2:</label> <input type="text"/> </div> </div> How to do it... The first thing we'll need to define is a custom CSS class used to properly align the icon once we place it in the title bar of the dialog. The CSS looks like this: .ui-dialog-icon { float: left; margin-right: 5px; } Next, we have our JavaScript code to customize the dialog widget by adding a new icon option as well as creating an instance of the widget using our HTML as the source: (function( $, undefined ) { $.widget( "ab.dialog", $.ui.dialog, { options: { icon: false }, _create: function() { this._super(); if ( this.options.icon ) { var iconClass = "ui-dialog-icon ui-icon " + this.options.icon; this.uiDialog.find( ".ui-dialog-titlebar" ) .prepend( $( "<span/>" ).addClass( iconClass )); } }, }); })( jQuery ); $(function() { $( "#dialog" ).dialog({ icon: "ui-icon-pencil", buttons: { Save: function() { $( this ).dialog( "close" ) } } }); }); The resulting dialog, when opened, should look something like the following: How it works... For this particular dialog instance, we would like to display the pencil icon. Our icon option we've added to the dialog widget allows the developer to specify an icon class from the theme framework. In this case, it's ui-icon-pencil. The new icon option has a default value of false. We're overriding the default dialog implementation of the _create() method so that we can inject a new span element into the dialog title bar if the icon option was provided. This new span element gets the icon class passed as the new option value, in addition to the ui-dialog-icon class, which is used to position the icon we defined earlier. Adding actions to the dialog title By default, the dialog widget provides the user with one action that doesn't require developer intervention—the close button in the title bar. This is a universal action that applies to almost any dialog, as users would expect to be able to close them. Additionally, it isn't by accident that the close dialog action button is an icon positioned in the top-right corner of the dialog. This is a standard location and action in graphical windowing environments as well, in addition to other actions. Let's take a look at how we might go about extending the actions placed in the title bar of the dialog widget. How to do it... For this demonstration, we only need the following basic dialog HTML: <div id="dialog" title="Dialog Title"> <p>Basic dialog content</p> </div> Next, we'll implement our dialog specialization that adds a new option and some code that creates a new dialog instance using that option: (function( $, undefined ) { $.widget( "ab.dialog", $.ui.dialog, { options: { iconButtons: false }, _create: function() { this._super(); var $titlebar = this.uiDialog.find( ".ui-dialog-titlebar" ); $.each( this.options.iconButtons, function( i, v ) { var button = $( "<button/>" ).text( v.text ), right = $titlebar.find( "[role='button']:last" ) .css( "right" ); button.button( { icons: { primary: v.icon }, text: false } ) .addClass( "ui-dialog-titlebar-close" ) .css( "right", (parseInt(right) + 22) + "px" ) .click( v.click ) .appendTo( $titlebar ); }); } }); })( jQuery ); $(function() { $( "#dialog" ).dialog({ iconButtons: [ { text: "Search", icon: "ui-icon-search", click: function( e ) { $( "#dialog" ).html( "<p>Searching...</p>" ); } }, { text: "Add", icon: "ui-icon-plusthick", click: function( e ) { $( "#dialog" ).html( "<p>Adding...</p>" ); } } ] }); }); When this dialog is opened, we'll see the new action buttons we passed to the dialog in the top-right corner, as shown in the following screenshot: How it works... We've created a new option for the dialog called iconButtons. This new option expects an array of objects, where each object has attributes related to an action button. Things like the text, the icon class, and the click event have to be executed when the user opens the dialog, and clicks on the button. The bulk of the work in this customization takes place in our version of the _create() method. Here, we iterate over each button supplied in the iconButtons option. The first thing we do when inserting a new button into the title bar is create the button element. We also get the width of the last action button added using the .ui-dialog-titlebar [role='button']:last selector (this is needed to compute the horizontal placement of the action button). Next, we bind the click event as specified in the button configuration. For each button in the array that we're adding, we want it placed to the left of the previous button. So when we first start iterating over the iconButtons array, the default close action is the last button in the title bar. Since the CSS structure requires a fixed right value, we have to compute it. And to do that, we need the value of the last button in the list. Applying effects to dialog resize interactions By default, the dialog widget allows users to resize by dragging the resize handle. The actual resize capability is provided by the resizable() interaction widget setup internally by the dialog when the resizable option is true. Let's take a look at how to gain access to the internal resizable component, so that we can use the animate feature. This option, when set on a resizable component, delays the redrawing of the resized component until the user has stopped dragging the resize handle. Getting ready... We only need simple dialog HTML for this demonstration, like this: <div id="dialog" title="Dialog Title"> <p>Basic dialog content</p> </div> How to do it... Let's add a new option to the dialog widget called animateResize. When this option is true, we'll turn on the animate option of the internal resizable interaction widget. (function( $, undefined ) { $.widget( "ab.dialog", $.ui.dialog, { options: { animateResize: false }, _makeResizable: function( handles ) { handles = (handles === undefined ? this.options.resizable : handles); var that = this, options = this.options, position = this.uiDialog.css( "position" ), resizeHandles = typeof handles === 'string' ? handles: "n,e,s,w,se,sw,ne,nw"; function filteredUi( ui ) { return { originalPosition: ui.originalPosition, originalSize: ui.originalSize, position: ui.position, size: ui.size }; } this.uiDialog.resizable({ animate: this.options.animateResize, cancel: ".ui-dialog-content", containment: "document", alsoResize: this.element, maxWidth: options.maxWidth, maxHeight: options.maxHeight, minWidth: options.minWidth, minHeight: this._minHeight(), handles: resizeHandles, start: function( event, ui ) { $( this ).addClass( "ui-dialog-resizing" ); that._trigger( "resizeStart", event, filteredUi( ui ) ); }, resize: function( event, ui ) { that._trigger( "resize", event, filteredUi( ui ) ); }, stop: function( event, ui ) { $( this ).removeClass( "ui-dialog-resizing" ); options.height = $( this ).height(); options.width = $( this ).width(); that._trigger( "resizeStop", event, filteredUi( ui ) ); if ( that.options.modal ) { that.overlay.resize(); } } }) .css( "position", position ) .find( ".ui-resizable-se" ) .addClass( "ui-icon ui-icon-grip-diagonal-se" ); } }); })( jQuery ); $(function() { $( "#dialog" ).dialog({ animateResize: true }); }); When this dialog is created and displayed, you'll be able to resize the dialog, observing that the actual resize is now animated. How it works... We've added the animateResize option to the dialog and provided it with a default value of false. To actually perform this capability, we've completely overwritten the _makeResizable() method, which the dialog widget uses internally when the dialog is created. In fact, we've taken the internal code for _makeResizable() and changed only one thing about it—animate: this.options.animateResize. This is slightly redundant, copying all this code for turning on a simple feature like animating the dialog resize interaction. Indeed, it isn't the ideal solution. A better approach would be to call the _super() version of _makeResizable(), then just turn on animate by calling this.uiDialog.resizable( "option", "animate", true ). But at the time of this writing, this doesn't behave as expected. Our alternative route, even though it involves redundant code, just goes to show the flexibility of the widget factory. If this animation quality were a real requirement of a user interface, we quickly found a work-around with a negligible trade-off. Using modal dialogs for messages The dialog widget has a modal option reserved for when we need to focus the user's attention on just one thing. This option displays the dialog while preventing the user from interacting with the rest of the user interface. They have no choice but to take notice. This goes without saying, the modal dialog should be used sparingly, especially if you want to use it to broadcast messages to the user. Let's look at how we can strip down the dialog in order to construct a generic notification tool in our application. It is a modal dialog in essence that is used for those cases where we cannot let the user continue what they're doing without ensuring they've seen our message. Getting ready... Here is what the HTML we'll need for this example looks like. Notice that the #notify div, which will become a dialog widget, has no content as our new notify widget will supply some. <div id="notify"></div> <button id="show-info">Show Info</button> <button id="show-error">Show Error</button> How to do it... Let's go ahead and define a new notify widget, capable of displaying both error and information messages to the user like this: (function( $, undefined ) { $.widget( "ab.notify", $.ui.dialog, { options: { modal: true, resizable: false, draggable: false, minHeight: 100, autoOpen: false, error: false }, open: function() { var error = this.options.error, newClass = error ? "ui-state-error" : "ui-state-highlight", oldClass = error ? "ui-state-highlight" : "ui-state-error"; this.element.html( this.options.text ); this.uiDialog.addClass( newClass ) .removeClass( oldClass ) .find( ".ui-dialog-titlebar" ) .removeClass( "ui-widget-header ui-corner-all" ); this._super(); }, }); })( jQuery ); $(function() { $( "#notify" ).notify(); $( "#show-info, #show-error" ).button(); $( "#show-info" ).click( function( e ) { $( "#notify" ).notify( "option", { error: false, text: "Successfully completed task" }); $( "#notify" ).notify( "open" ); }); $( "#show-error" ).click(function( e ) { $( "#notify" ).notify( "option", { error: true, text: "Failed to complete task" }); $( "#notify" ).notify( "open" ); }) The two buttons we've created here are used for demonstrating the notify widget's capabilities. If you click the #show-info button, you'll see the following informational message: If you click the #show-error button, you'll see this error message: How it works... The notify widget we've just created inherits all of the dialog widget's capabilities. The first thing we define in our widget is the available options. In this case, we're extending the options object of the dialog widget, and adding some new options. You'll notice, too, that we're providing some updated default values for the dialog options such as turning modal on and turning draggable off. Every notify instance will share these defaults, so it doesn't make much sense to have to define them each and every time. The open() method belongs to the dialog widget, and we're overriding it here to implement custom functionality that inserts the text of the notification message into the dialog content. We also set the state of the dialog based on the error option. If this is an error message, we apply the ui-state-error class to the entire dialog. If the error option is false, we apply the ui-state-highlight class. Finally, the dialog title bar component is stripped down by removing some classes, since we're not using it in the message display. In the application code, the first thing we're creating is an instance of the notify widget. We then create the demo buttons and bind the click event to the functionality that will display an error message or an informational one, depending on which button is clicked. Summary This article covered loading data and dialog display issues. It also covered topics like adding effects to the widget and changing the dialog title bar.   Resources for Article :   Further resources on this subject: jQuery Animation: Tips and Tricks [Article] Getting Started with jQuery [Article] New Effects Added by jQuery UI [Article]
Read more
  • 0
  • 0
  • 1598

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

Creating your first FreeMarker Template

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

article-image-building-your-first-zend-framework-application
Packt
26 Jul 2013
15 min read
Save for later

Building Your First Zend Framework Application

Packt
26 Jul 2013
15 min read
(For more resources related to this topic, see here.) Prerequisites Before you get started with setting up your first ZF2 Project, make sure that you have the following software installed and configured in your development environment: PHP Command Line Interface Git : Git is needed to check out source code from various github.com repositories Composer : Composer is the dependency management tool used for managing PHP dependencies The following commands will be useful for installing the necessary tools to setup a ZF2 Project: To install PHP Command Line Interface: $ sudo apt-get install php5-cli To install Git: $ sudo apt-get install git To install Composer: $ curl -s https://getcomposer.org/installer | php ZendSkeletonApplication ZendSkeletonApplication provides a sample skeleton application that can be used by developers as a starting point to get started with Zend Framework 2.0. The skeleton application makes use of ZF2 MVC, including a new module system. ZendSkeletonApplication can be downloaded from GitHub (https://github.com/zendframework/ZendSkeletonApplication). Time for action – creating a Zend Framework project To set up a new Zend Framework project, we will need to download the latest version of ZendSkeletonApplication and set up a virtual host to point to the newly created Zend Framework project. The steps are given as follows: Navigate to a folder location where you want to set up the new Zend Framework project: $ cd /var/www/ Clone the ZendSkeletonApplication app from GitHub: $ git clone git://github.com/zendframework/ ZendSkeletonApplication.git CommunicationApp In some Linux configurations, necessary permissions may not be available to the current user for writing to /var/www. In such cases, you can use any folder that is writable and make necessary changes to the virtual host configuration. Install dependencies using Composer: $ cd CommunicationApp/ $ php composer.phar self-update $ php composer.phar install The following screenshot shows how Composer downloads and installs the necessary dependencies: Before adding a virtual host entry we need to set up a hostname entry in our hosts file so that the system points to the local machine whenever the new hostname is used. In Linux this can be done by adding an entry to the /etc/hosts file: $ sudo vim /etc/hosts In Windows, this file can be accessed at %SystemRoot%system32driversetchosts. Add the following line to the hosts file: 127.0.0.1 comm-app.local The final hosts file should look like the following: Our next step would be to add a virtual host entry on our web server; this can be done by creating a new virtual host's configuration file: $ sudo vim /usr/local/zend/etc/sites.d/vhost_comm-app-80.conf This new virtual host filename could be different for you depending upon the web server that you use; please check out your web server documentation for setting up new virtual hosts. For example, if you have Apache2 running on Linux, you will need to create the new virtual host file in /etc/apache2/sites-available and enable the site using the command a2ensite comm-app.local. Add the following configuration to the virtual host file: <VirtualHost *:80> ServerName comm-app.local DocumentRoot /var/www/CommunicationApp/public SetEnv APPLICATION_ENV "development" <Directory /var/www/CommunicationApp/public> DirectoryIndex index.php AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost> If you are using a different path for checking out the ZendSkeletonApplication project make sure that you include that path for both DocumentRoot and Directory directives. After configuring the virtual host file, the web server needs to be restarted: $ sudo service zend-server restart Once the installation is completed, you should be able to open http://comm-app.local on your web browser. This should take you to the following test page : Test rewrite rules In some cases, mod_rewrite may not have been enabled in your web server by default; to check if the URL redirects are working properly, try to navigate to an invalid URL such as http://comm-app.local/12345; if you get an Apache 404 page, then the .htaccess rewrite rules are not working; they will need to be fixed, otherwise if you get a page like the following one, you can be sure of the URL working as expected. What just happened? We have successfully created a new ZF2 project by checking out ZendSkeletonApplication from GitHub and have used Composer to download the necessary dependencies including Zend Framework 2.0. We have also created a virtual host configuration that points to the project's public folder and tested the project in a web browser. Alternate installation options We have seen just one of the methods of installing ZendSkeletonApplication; there are other ways of doing this. You can use Composer to directly download the skeleton application and create the project using the following command: $ php composer.phar create-project --repositoryurl="http://packages.zendframework.com" zendframework/skeleton-application path/to/install You can also use a recursive Git clone to create the same project: $ git clone git://github.com/zendframework/ZendSkeletonApplication.git --recursive Refer to: http://framework.zend.com/downloads/skeleton-app Zend Framework 2.0 – modules In Zend Framework, a module can be defined as a unit of software that is portable and reusable and can be interconnected to other modules to construct a larger, complex application. Modules are not new in Zend Framework, but with ZF2, there is a complete overhaul in the way modules are used in Zend Framework. With ZF2, modules can be shared across various systems, and they can be repackaged and distributed with relative ease. One of the other major changes coming into ZF2 is that even the main application is now converted into a module; that is, the application module. Some of the key advantages of Zend Framework 2.0 modules are listed as follows: Self-contained, portable, reusable Dependency management Lightweight and fast Support for Phar packaging and Pyrus distribution Zend Framework 2.0 – project folder structure The folder layout of a ZF2 project is shown as follows: Folder name Description config Used for managing application configuration. data Used as a temporary storage location for storing application data including cache files, session files, logs, and indexes. module Used to manage all application code. module/Application This is the default application module that is provided with ZendSkeletonApplication. public This is the default application module that is provided with ZendSkeletonApplication. vendor Used to manage common libraries that are used by the application. Zend Framework is also installed in this folder. vendor/zendframework endor/zendframework Zend Framework 2.0 is installed here. Time for action – creating a module Our next activity will be about creating a new Users module in Zend Framework 2.0. The Users module will be used for managing users including user registration, authentication, and so on. We will be making use of ZendSkeletonModule provided by Zend, shown as follows: Navigate to the application's module folder: $ cd /var/www/CommunicationApp/ $ cd module/ Clone ZendSkeletonModule into a desired module name, in this case it is Users: $ git clone git://github.com/zendframework/ZendSkeletonModule.git Users After the checkout is complete, the folder structure should look like the following screenshot: Edit Module.php ; this file will be located in the Users folder under modules (CommunicationApp/module/Users/module.php) and change the namespace to Users. Replace namespace ZendSkeletonModule; with namespace Users;. The following folders can be removed because we will not be using them in our project: * Users/src/ZendSkeletonModule * Users/view/zend-skeleton-module What just happened? We have installed a skeleton module for Zend Framework; this is just an empty module, and we will need to extend this by creating custom controllers and views. In our next activity, we will focus on creating new controllers and views for this module. Creating a module using ZFTool ZFTool is a utility for managing Zend Framework applications/projects, and it can also be used for creating new modules; in order to do that, you will need to install ZFTool and use the create module command to create the module using ZFTool: $ php composer.phar require zendframework/zftool:dev-master $ cd vendor/zendframework/zftool/ $ php zf.php create module Users2 /var/www/CommunicationApp Read more about ZFTool at the following link: http://framework.zend.com/manual/2.0/en/modules/zendtool.introduction.html MVC layer The fundamental goal of any MVC Framework is to enable easier segregation of three layers of the MVC, namely, model, view, and controller. Before we get to the details of creating modules, let's quickly try to understand how these three layers work in an MVC Framework: Model : The model is a representation of data; the model also holds the business logic for various application transactions. View : The view contains the display logic that is used to display the various user interface elements in the web browser. Controller : The controller controls the application logic in any MVC application; all actions and events are handled at the controller layer. The controller layer serves as a communication interface between the model and the view by controlling the model state and also by representing the changes to the view. The controller also provides an entry point for accessing the application. In the new ZF2 MVC structure, all the models, views, and controllers are grouped by modules. Each module will have its own set of models, views, and controllers, and will share some components with other modules. Zend Framework module – folder structure The folder structure of Zend Framework 2.0 module has three vital components—the configurations, the module logic, and the views. The following table describes how contents in a module are organized: Folder name Description config Used for managing module configuration src Contains all module source code, including all controllers and models view Used to store all the views used in the module Time for action – creating controllers and views Now that we have created the module, our next step would be having our own controllers and views defined. In this section, we will create two simple views and will write a controller to switch between them: Navigate to the module location: $ cd /var/www/CommunicationApp/module/Users Create the folder for controllers: $ mkdir -p src/Users/Controller/ Create a new IndexController file, < ModuleName >/src/<ModuleName>/Controller/: $ cd src/Users/Controller/ $ vim IndexController.php Add the following code to the IndexController file: <?php namespace UsersController; use ZendMvcControllerAbstractActionController; use ZendViewModelViewModel; class IndexController extends AbstractActionController { public function indexAction() { $view = new ViewModel(); return $view; } public function registerAction() { $view = new ViewModel(); $view->setTemplate('users/index/new-user'); return $view; } public function loginAction() { $view = new ViewModel(); $view->setTemplate('users/index/login'); return $view; } } The preceding code will do the following actions; if the user visits the home page, the user is shown the default view; if the user arrives with an action register, the user is shown the new-user template; and if the user arrives with an action set to login, then the login template is rendered. Now that we have created the controller, we will have to create necessary views to render for each of the controller actions. Create the folder for views: $ cd /var/www/CommunicationApp/module/Users $ mkdir -p view/users/index/ Navigate to the views folder, <Module>/view/<module-name>/index: $ cd view/users/index/ Create the following view files: index login new-user For creating the view/users/index/index.phtml file, use the following code: <h1>Welcome to Users Module</h1> <a href="/users/index/login">Login</a> | <a href = "/users/index/register">New User Registration</a> For creating the view/users/index/login.phtml file, use the following code: <h2> Login </h2> <p> This page will hold the content for the login form </p> <a href="/users"><< Back to Home</a> For creating the view/users/index/new-user.phtml file, use the following code: <h2> New User Registration </h2> <p> This page will hold the content for the registration form </p> <a href="/users"><< Back to Home</a> What just happened? We have now created a new controller and views for our new Zend Framework module; the module is still not in a shape to be tested. To make the module fully functional we will need to make changes to the module's configuration, and also enable the module in the application's configuration. Zend Framework module – configuration Zend Framework 2.0 module configuration is spread across a series of files which can be found in the skeleton module. Some of the configuration files are described as follows: Module.php: The Zend Framework 2 module manager looks for the Module.php file in the module's root folder. The module manager uses the Module.php file to configure the module and invokes the getAutoloaderConfig() and getConfig() methods. autoload_classmap.php: The getAutoloaderConfig() method in the skeleton module loads autoload_classmap.php to include any custom overrides other than the classes loaded using the standard autoloader format. Entries can be added or removed to the autoload_classmap.php file to manage these custom overrides. config/module.config.php: The getConfig() method loads config/module.config.php; this file is used for configuring various module configuration options including routes, controllers, layouts, and various other configurations. Time for action – modifying module configuration In this section will make configuration changes to the Users module to enable it to work with the newly created controller and views using the following steps: Autoloader configuration – The default autoloader configuration provided by the ZendSkeletonModule needs to be disabled; this can be done by editing autoload_classmap.php and replacing it with the following content: <?php return array(); Module configuration – The module configuration file can be found in config/module.config.php; this file needs to be updated to reflect the new controllers and views that have been created, as follows: Controllers – The default controller mapping points to the ZendSkeletonModule; this needs to be replaced with the mapping shown in the following snippet: 'controllers' => array( 'invokables' => array( 'UsersControllerIndex' => 'UsersControllerIndexController', ), ), Views – The views for the module have to be mapped to the appropriate view location. Make sure that the view uses lowercase names separated by a hyphen (for example, ZendSkeleton will be referred to as zend-skeleton): 'view_manager' => array( 'template_path_stack' => array( 'users' => __DIR__ . '/../view', ), ), Routes – The last module configuration is to define a route for accessing this module from the browser; in this case we are defining the route as /users, which will point to the index action in the Index controller of the Users module: 'router' => array( 'routes' => array( 'users' => array( 'type' => 'Literal', 'options' => array( 'route' => '/users', 'defaults' => array( '__NAMESPACE__' => 'UsersController', 'controller' => 'Index', 'action' => 'index', ), ), After making all the configuration changes as detailed in the previous sections, the final configuration file, config/module.config.php, should look like the following: <?php return array( 'controllers' => array( 'invokables' => array( 'UsersControllerIndex' => 'UsersControllerIndexController', ), ), 'router' => array( 'routes' => array( 'users' => array( 'type' => 'Literal', 'options' => array( // Change this to something specific to your module 'route' => '/users', 'defaults' => array( //Change this value to reflect the namespace in which // the controllers for your module are found '__NAMESPACE__' => 'UsersController', 'controller' => 'Index', 'action' => 'index', ), ), 'may_terminate' => true, 'child_routes' => array( // This route is a sane default when developing a module; // as you solidify the routes for your module, however, // you may want to remove it and replace it with more // specific routes. 'default' => array( 'type' => 'Segment', 'options' => array( 'route' => '/[:controller[/:action]]', 'constraints' => array( 'controller' => '[a-zA-Z][a-zA-Z0-9_-]*', 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', ), 'defaults' => array( ), ), ), ), ), ), ), 'view_manager' => array( 'template_path_stack' => array( 'users' => __DIR__ . '/../view', ), ), ); Application configuration – Enable the module in the application's configuration—this can be done by modifying the application's config/application.config.php file, and adding Users to the list of enabled modules: 'modules' => array( 'Application', 'Users', ), To test the module in a web browser, open http://comm-app.local/users/ in your web browser; you should be able to navigate within the module. The module home page is shown as follows: The registration page is shown as follows: What just happened? We have modified the configuration of ZendSkeletonModule to work with the new controller and views created for the Users module. Now we have a fully-functional module up and running using the new ZF module system. Have a go hero Now that we have the knowledge to create and configure own modules, your next task would be to set up a new CurrentTime module. The requirement for this module is to render the current time and date in the following format: Time: 14:00:00 GMT Date: 12-Oct-2012 Summary We have now learned about setting up a new Zend Framework project using Zend's skeleton application and module. In our next chapters, we will be focusing on further development on this module and extending it into a fully-fledged application. Resources for Article : Further resources on this subject: Magento's Architecture: Part 2 [Article] Authentication with Zend_Auth in Zend Framework 1.8 [Article] Authorization with Zend_Acl in Zend Framework 1.8 [Article]
Read more
  • 0
  • 0
  • 7288

article-image-scaffolding-command-line-tool
Packt
25 Jul 2013
4 min read
Save for later

Scaffolding with the command-line tool

Packt
25 Jul 2013
4 min read
(For more resources related to this topic, see here.) CakePHP comes packaged with the Cake command-line tool, which provides a number of code generation tools for creating models, controllers, views, data fixtures, and more, all on the fly. Please note that this is great for prototyping, but is non-ideal for a production environment. On your command line, from the cake-starter folder, type the following: cd appConsolecake bake You will see something similar to the following: > Console/cake bakeWelcome to CakePHP v2.2.3 Console---------------------------------------------------------------App : appPath: /path/to/app/---------------------------------------------------------------Interactive Bake Shell---------------------------------------------------------------[D]atabase Configuration[M]odel[V]iew[C]ontroller[P]roject[F]ixture[T]est case[Q]uitWhat would you like to Bake? (D/M/V/C/P/F/T/Q)> As you can see, there's a lot to be done with this tool. Note that there are other commands beside bake, such as schema, which we be our main focus in this article. Creating the schema definition Inside the app/Config/Schema folder, create a file called glossary.php. Insert the following code into this file: <?php/** * This schema provides the definitions for the core tables in the glossary app. * * @var $glossary_terms - The main terms/definition table for the app * @var $categories - The categories table * @var $terms_categories - The lookup table, no model will be created. * * @author mhenderson * */class GlossarySchema extends CakeSchema { public $glossaryterms = array( 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'title' => array('type' => 'string', 'null' => false, 'length' => 100), 'definition' => array('type' => 'string', 'null' => false, 'length' => 512) ); public $categories = array( 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => false, 'length' => 100), 'definition' => array('type' => 'string', 'null' => false, 'length' => 512) ); public $glossaryterms_categories = array( 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'glossaryterm_id' => array('type' => 'integer', 'null' => false), 'category_id' => array('type' => 'string', 'null' => false) );} This class definition represents three tables: glossaryterms , categories, and a lookup table to facilitate the relationship between the two tables. Each variable in the class represents a table, and the array keys inside of the variable represent the fields in the table. As you can see, the first two tables match up with our earlier architecture description. Creating the database schema On the command line, assuming you haven't moved to any other folders, type the following command: Console/cake schema create glossary You should then see the following responses. When prompted, type y once to drop the tables, and again to create them. Welcome to CakePHP v2.2.3 Console---------------------------------------------------------------App : appPath: /path/to/app---------------------------------------------------------------Cake Schema Shell---------------------------------------------------------------The following table(s) will be dropped.glossarytermscategoriesglossaryterms_categoriesAre you sure you want to drop the table(s)? (y/n)[n] > yDropping table(s).glossaryterms updated.categories updated.glossaryterms_categories updated.The following table(s) will be created.glossarytermscategoriesglossaryterms_categoriesAre you sure you want to create the table(s)? (y/n)[y] > yCreating table(s).glossaryterms updated.categories updated.glossaryterms_categories updated.End create. If you look at your database now, you will notice that the three tables have been created. We can also make modifications to the glossary.php file and run the cake schema command again to update it. If you want to try something a little more daring, you can use the migrations plugin found at https://github.com/CakeDC/migrations. This plugin allows you to save "snapshots" of your schema to be recalled later, and also allows you to write custom scripts to migrate "up" to a certain snapshot version, or migrate "down" in the event of an emergency or a mistake. Summary In this article we saw the use of the schema tool and also its database. Resources for Article: Further resources on this subject: Create a Quick Application in CakePHP: Part 1 [Article] Working with Simple Associations using CakePHP [Article] Creating and Consuming Web Services in CakePHP 1.3 [Article]
Read more
  • 0
  • 0
  • 1840

article-image-programming-issues
Packt
25 Jul 2013
12 min read
Save for later

Programming Issues

Packt
25 Jul 2013
12 min read
(For more resources related to this topic, see here.) Creating an issue from a plugin Here, we will see how to programmatically create an issue from a plugin. Prior to Version 4.1, JIRA used IssueManager to create an issue. From JIRA 4.1, there is this IssueService class that drives the issue operations. Since IssueService is recommended over IssueManager. How to do it... The main advantage of using IssueService over the IssueManager class is that it takes care of the validation and error handling. The following are the steps to create an issue using the IssueService class: Create an instance of the IssueService class. You can either inject it in the constructor or get it from the ComponentAccessor class, as shown: IssueService issueService = ComponentAccessor.getIssueService(); Create the issue input parameters. In this step, we will set all the values that are required to create the issue using the IssueInputParameters class. Create an instance of the IssueInputParameters class: IssueInputParameters issueInputParameters = newIssueInputParametersImpl(); Populate the IssueInputParameters class with the values required to create the issue as shown in the next few lines of code: issueInputParameters.setProjectId(10000L).setIssueTypeId("5").setSummary("Test Summary").setReporterId("admin").setAssigneeId("admin").setDescription("Test Description").setStatusId("1").setPriorityId("2").setFixVersionIds(10000L, 12121L); Make sure all the required values such as project, issue type, summary, and other mandatory values required when the issue is created using the user interface, are set on the IssueInputParameters class. Here, we have used test values, but make sure to replace them with appropriate values. For example, the project, issue type ID, priority ID, Fix version IDs, reporter, and assignee should have appropriate values. Validate the input parameters using IssueService: CreateValidationResult createValidationResult = issueService.validateCreate(user, issueInputParameters); Here, the user is the one creating the issue. The validation is done based on the user permissions and the createValidationResult variable will have errors if the validation fails due to permission issues or due to invalid input parameters! If the createValidationResult variable is valid, create the issue using IssueService: if (createValidationResult.isValid()) {IssueResult createResult = issueService.create(user,createValidationResult);} Here, we use the createValidationResult object to create the issue, as it already has the processed input parameters. If the result is not valid, handle the errors as shown in the following code: if (!createValidationResult.isValid()) {Collection<String> errorMessages = createValidationResult.getErrorCollection().getErrorMessages();for (String errorMessage : errorMessages) {System.out.println(errorMessage);}Map<String, String> errors = createValidationResult.getErrorCollection().getErrors();Set<String> errorKeys = errors.keySet();for (String errorKey : errorKeys) {System.out.println(errors.get(errorKey));}} Here, we just print the error to the console if the result is invalid. The errorMessages object will have all non-field-specific errors such as permission issue-related errors, and so on, but any field-specific errors, such as input validation errors, will appear in the errors map where the key will be the field name. We should handle both the error types as appropriate. After the creation of an issue, check whether the createResult object is valid or not. If not, handle it appropriately. The createResult object will have errors only if there is a severe problem with JIRA (for example, if you can't communicate with the database, the workflow has changed since you invoked validate, and so on). if (!createResult.isValid()) {Collection<String> errorMessages = createResult.getErrorCollection().getErrorMessages();for (String errorMessage : errorMessages) {System.out.println(errorMessage);}} Here again, we just print the error to the console. If createResult is valid, then the issue is created successfully and you can retrieve it as: MutableIssue issue = createResult.getIssue(); How it works... By using IssueService, JIRA now validates the inputs we give it using the rules we have set up in JIRA via the user interfaces, such as the mandatory fields, permission checks, individual field validations, and so on. Behind the scenes, it still uses the IssueManager class. There's more... As mentioned before, prior to JIRA 4.1, we needed to use the IssueManager class to create the issues. It can still be used in JIRA 4.1 and higher, but this is not recommended as it overrides all the validations. But then again, what if you want to override those validations due to some reason? For example, to skip permission checks or field screen validations inside the plugin? In such cases, we might still need IssueManager. Using IssueManager to create the issue Follow these steps to create an issue with the IssueManager class: Initialize an issue object using the IssueFactory class: MutableIssue issue = ComponentAccessor.getIssueFactory().getIssue(); Set all the fields required on the issue object: issue.setProjectId(10000L);issue.setIssueTypeId("5");issue.setAssigneeId("admin"); Create the issue using IssueManager: Issue createdIssue = ComponentAccessor.getIssueManager().createIssueObject(user, issue); Handle CreateException to catch any errors. Creating subtasks on an issue Here, we will demonstrate how to create a subtask from a JIRA plugin. It is very similar to the issue creation, but there are some notable differences. Subtasks are useful for splitting up a parent issue into a number of tasks, which can be assigned and tracked separately. The progress on an issue is generally a sum of the progress on all its subtasks, although people use it for a lot of other purposes too. How to do it... There are two steps to creating a subtask: Create an issue object. A subtask object is nothing but an issue object in the backend. The only difference is that it has a parent issue associated with it. So, when we create a subtask issue object, we will have to define the parent issue in addition to what we normally do while creating a normal issue. Link the newly created subtask issue to the parent issue. Let's see these steps in more detail: Create the subtask issue object. Here, the IssueInputParameters interface is constructed (after changing the methods such as setIssueTypeId() appropriately). For this issue, we will use the validateSubTaskCreate method—which takes an extra parameter named parentId— instead of validateCreate: CreateValidationResult createValidationResult = issueService.validateSubTaskCreate(user, parent.getId(), issueInputParameters); Here, parent is the issue object on which we are creating the subtask. Create an issue after checking for errors, as we have seen previously: if (createValidationResult.isValid()) {IssueResult createResult = issueService.create(user,createValidationResult);} Create a link between the newly created subtask issue and the parent issue: Get an instance of SubTaskManager. You can either inject it in the constructor or get it from ComponentAccessor as follows: SubTaskManager subTaskManager = ComponentAccessor.getSubTaskManager(); Create the subtask link: subTaskManager.createSubTaskIssueLink(parent, createResult.getIssue(), user); The subtask should now be created with a link back to the original parent issue. Updating an issue Here, let's look at editing an existing issue. Users can edit the issue to update one or more fields, and there are screen schemes or field configurations to define what a user can see while editing an issue. Moreover, there is the edit project permission option to limit editing to selected users, groups, or roles. Programmatically editing an issue also takes these things into account. How to do it... Let's assume that we have an existing issue object. We will just modify the summary to a new summary. Following are the steps to do this: Create the IssueInputParameters object with the input fields that need to be modified: IssueInputParameters issueInputParameters = newIssueInputParametersImpl();issueInputParameters.setSummary("Modified Summary"); If you do not want to retain the existing values and just want the summary on the issue to be updated, you can set the retainExistingValuesWhenParameterNotProvided flag as shown: issueInputParameters.setRetainExistingValuesWhenParameterNotProvided(false); Validate the input parameters using IssueService: UpdateValidationResult updateValidationResult = issueService.validateUpdate(user, issue.getId(), issueInputParameters); Here, issue is the existing issue object. If updateValidationResult is valid, update the issue: if (updateValidationResult.isValid()) {IssueResult updateResult = issueService.update(user,updateValidationResult);} If it is not valid, handle the errors as we did when creating the issue. Validate updateResult and handle the error, if any. If it is not valid, the updated issue object can be retrieved as: MutableIssue updatedIssue = updateResult.getIssue(); Deleting an issue Here, let us look at deleting an issue programmatically. How to do it... Let us assume that we have an existing issue object. For deletion as well, we will use the IssueService class. Following are the steps to do this: Validate the delete operation on the issue using IssueService: DeleteValidationResult deleteValidationResult = issueService.validateDelete(user, issue.getId()); Here, issue is the existing issue object that needs to be deleted. If deleteValidationResult is valid, invoke the delete operation: if (deleteValidationResult.isValid()) {ErrorCollection deleteErrors = issueService.delete(user,deleteValidationResult);} If deleteValidationResult is invalid, handle the errors appropriately. Confirm whether the deletion was successful by checking the deleteErrors collection: if (deleteErrors.hasAnyErrors()){Collection<String> errorMessages = deleteErrors.getErrorMessages();for (String errorMessage : errorMessages) {System.out.println(errorMessage);}} else {System.out.println("Deleted Succesfully!");} Adding new issue operations Here, we will look at adding new operations to an issue. The existing issue operations include Edit Issue, Clone Issue, and so on, but most of the time, people tend to look for similar operations with variations or entirely new operations that they can perform on an issue. Prior to JIRA 4.1, the issue operations were added using the Issue Operations Plugin Module (http://confluence.atlassian.com/display/JIRADEV/Issue+Operations+Plugin+Module). But since JIRA 4.1, new issue operations are added using the Web Item Plugin Module (http://confluence.atlassian.com/display/JIRADEV/Web+Item+Plugin+Module). A Web Item Plugin module is a generic module that is used to define links in various application menus. One such menu is the issue operations menu. Here, we will only concentrate on using the web-item module to create issue operations. Getting ready Create a skeleton plugin using Atlassian Plugin SDK. How to do it... Creating a web item is pretty easy! All we need to do is to place it in the appropriate section. There are already defined web sections in JIRA, and we can add more sections using the Web Section module if needed. Let us create a new operation that lets us administer the project of an issue when we are on the View Issue page. All we need here is to add an operation that takes us to the Administer Project page. Following are the steps to create the new operation: Identify the web section where the new operation should be placed. For issue operations, JIRA already has multiple web sections defined. We can add our new operation on any one of these sections. The following is a diagram from the Atlassian documentation detailing with each of the available web sections for the issue operations: If we want to add a new operation along with Move, Link, and so on, we need to add the new web item under the operations-operations section. If you are rather hoping to add it right at the top, along with Edit, Assign, and Comment, the section must be operations-top-level. We can reorder the operation using the weight attribute. Define the web item module in the plugin descriptor with the section identified in the previous step! For our example, the module definition in atlassian-plugin.xml will look like the following: <web-item key="manage-project" name="Manage Project"section="operations-operations" weight="100"><label>Manage Project</label><tooltip>Manages the Project in which the issue belongs </tooltip><link linkId="manage-project-link">/plugins/servlet/projectconfig/${issue.project.key}</link></web-item> As you can see, this has a unique key and a human-readable name. The section here is operations-operations. The weight attribute is used to reorder the operations as we saw earlier, and here we use weight as 100 to put it at the bottom of the list. label is the name of the operation that will appear to the user. We can add a tooltip as well, which can have a friendly description of the operation. The next part, that is, the link attribute, is the most important one, as it links us to the operation that we want to perform. Essentially it is just a link, and hence you can use it to redirect to anywhere; the Atlassian site, for example. In our example, we need to take the user to the administer project area. Luckily, in this case, we know the servlet to be invoked, as it is an existing servlet in JIRA. All we need to do is to invoke the project-config servlet by passing the project key as well. The issue object is available on the view issue page as $issue, and hence we can retrieve the project ID on the link as ${issue.project.key}. In cases where we need to do new things, we will have to create an action or servlet by ourselves and point the link to that action/servlet. Package the plugin and deploy it. How it works... At runtime, you will see a new operation on the View Issue page on the More Actions drop-down menu, as shown in the next screenshot: After clicking on the link, the Administer Project screen will appear as expected. As you might have noticed, the URL is populated with the correct key from the expression ${issue.project.key}. Also, just change the section or weight and see how the operation appears at various places on the screen! There's more... Prior to JIRA 4.1, the Issue Operations module was used in the creation of new issue operations. You can find details about it in the Atlassian documentation at http://confluence.atlassian.com/display/JIRADEV/Issue+Operations+Plugin+Module.
Read more
  • 0
  • 0
  • 3305
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-installing-centos
Packt
25 Jul 2013
8 min read
Save for later

Installing CentOS

Packt
25 Jul 2013
8 min read
(For more resources related to this topic, see here.) Downloading CentOS and confirming the checksum on a Windows desktop In this article we will learn how to download and confirm the checksum of one or more CentOS 6 disk image(s) using a typical Windows desktop computer. CentOS is made available in various formats by HTTP, FTP, or via a Torrent-based client from a series of mirror sites located across the world. It supports both the 32-bit and 64-bit architectures, and having downloaded one or more image files, it is often a good idea to validate those files' checksum in order to ensure that any resulting media should function and perform as expected. Getting Ready To complete this recipe it is assumed that you are using a typical Windows-based computer (Windows 7, Windows Vista, or similar) with full administration rights. You will need an Internet connection to download the required installation files and access to a standard DVD/CD disk burner with the appropriate software in order to create the relevant installation disks. How to do it... Regardless as to what type of installation files you download, the following techniques can be applied to all image files supplied by the CentOS project: So let's begin by visiting http://www.centos.org/mirrors-list in your browser. This URL was correct at the time of writing this article, but if it's no longer functional or is not available, then simply visit http://www.centos.org and navigate to Downloads Mirrors | CentOS Public Mirror List| or review the links associated with the latest release announcements made on the home page. The mirror sites are categorized, so from the resulting list of links, choose a mirror that best suits your current location. For example, if you are in London (UK), you can choose European Mirrors (Countries N-Z). From the resulting list and depending on your preferred method of downloading the CentOS images, scroll down and choose a mirror site by selecting either, the HTTP or the FTP link. Having made your selection, you will now see a list of directories or folders that will allow you to choose the version of CentOS you want to install. To proceed, simply select the appropriate folder that reads 6.X, where X is the required minor release of CentOS 6. Having chosen the preferred minor release of CentOS you want to install, you will now see an additional list of directories that includes centosplus, contrib, cr, extras, fasttrack, isos, os, and updates. To proceed, choose the isos directory. At this point you are now given the opportunity to choose the preferred architecture. The directory labeled i386 is a container for the 32-bit version while the directory labeled x86_64 is a container for the 64-bit version. Make the appropriate selection to proceed. You will now be presented with a series of files available for download. Begin by downloading a copy of the valid checksum result labeled or identified as md5sum.txt. As this is a standard text file, place your mouse on the link, right-click and choose Save As to download a copy of md5sum.txt.When finished, store this file in a safe place for future reference. For the purpose of this recipe, it is assumed that all downloads will be stored in your C:Users<username>Downloads folder. Now, depending on which installation image best suits your needs, start downloading the relevant file(s) in the usual way. If you are new to CentOS or are intending to follow the recipes found throughout this article, then the minimal installation is ideal. However, you should be aware that there are other options available to you. For a full 64-bit DVD-based installation, you will need both: CentOS-6.X-x86_64-bin-DVD1.isoCentOS-6.X-x86_64-bin-DVD2.iso For a full 32-bit DVD-based installation, you will need both: CentOS-6.X-i386-bin-DVD1.isoCentOS-6.X-i386-bin-DVD2.iso For a minimal installation, you should choose either: CentOS-6.X-i386-minimal.iso (32-bit version)CentOS-6.X-x86_64-minimal.iso (64-bit version) For a network installation, you should choose either: CentOS-6.X-i386-netinstall.iso (32-bit version)CentOS-6.X-x86_64-netinstall.iso (64-bit version) If you choose to download a torrent file, then you will need to extract these files in the usual way in order to build the appropriate ISO image file(s). When you have finished downloading the required files, visit http://mirror.centos.org/centos/dostools/ in your browser. Now download the following DOS-based tool in order that we can use it to validate our installation files: md5sum.exe The full URL is http://mirror.centos.org/centos/dostools/md5sum.exe. It is assumed that you have downloaded all the files to the typical downloads folder of the current user profile on your Windows desktop (C:Users <username>Downloads), so when the download is complete, open Command Prompt (typically found at Start All Programs | Accessories | Command Prompt|) and type the following command to access this location: cd downloads To see the list of files and the relevant extensions, type the following command: dir The command prompt should now list all the files in your download folder (including all image files, md5sum.txt, and md5sum.exe). Based on the file names shown, modify the following command in order to check the checksum of your ISO image file and type: md5sum.exe your_image_file_name_here.iso For example, you can type md5sum.exe CentOS-6.X-x86_64-minimal.iso Press the Return key to proceed and then wait for the command prompt to respond. The response is known as the sum and the result could look like this: 087713752fa88c03a5e8471c661ad1a2 *CentOS-6.X-x86_64-minimal.iso Now look at the value given, this is known as the sum, and compare against the relevant listing for your particular image file listed in md5sum.txt. If both numbers match, then you can be confident that you have indeed downloaded a valid CentOS image file. Now repeat this process for any remaining image files and when you have finished,simply burn your image file(s) to a blank CD-Rom or DVD-Rom using your preferred desktop software. How it works… The act of downloading an installation image and validating the file's integrity is just the first step towards building the perfect server, and although the process of downloading CentOS is very simple, many do forget the need to confirm the checksum. So what have we learned from this experience? We began this recipe by showing you how to download CentOS by outlining the various optionsavailable to you. It is not expected that you will need to do this often, but during the course of this recipe you also learned how to navigate the CentOS Project website and select the best download location based on your current location. Having done this, our next step was to obtain a copy of md5sum.txt before downloading the preferred image files. The choice as to whether you selected a 32-bit or 64-bit version is largely dependent on the specification of your intended server. However, given the abilities of most modern computers, for most people the obvious choice will be the 64-bit version in order that you can take advantage of the improved code base and support more than 4 GB of RAM. The time required to complete the task of downloading the relevant files will depend largely on the speed of your Internet connection, but it was important that we obtained a copy of md5sum.exe in order to confirm file integrity and compare the value given against those listed in md5sum.txt. The DOS-based tool was obtained fromhttp://mirror.centos.org/centos/dostools/md5sum.exe. Having completed these steps, we then proceed to open a command prompt session and navigate to the expected destination of all the files by typing: cd downloads We then proceeded to view the contents of C:Users<username>Downloads by typing the following command: dir This action lists the filenames concerned, thereby enabling us to modify the following command in order to validate the appropriate ISO files: md5sum.exe your_image_file_name_here.iso The resulting response provides us with the checksum value of the file in question in order that we can compare it with the corresponding value found in md5sum.txt. For example,the content of md5sum.txt may look like this: 087713752fa88c03a5e8471c661ad1a2 CentOS-6.X-x86_64-minimal.iso Whereas the display in command prompt may show: 087713752fa88c03a5e8471c661ad1a2 *CentOS-6.X-x86_64-minimal.iso Summary You should repeat this process for all image files, and if these values match, then you can be confident that your download is verified. A fact that not only reduces the chance of wasting optical disks, but with security in mind, it also implies that what you downloaded is what you were expecting to download (and not something else). So remember, with every new release the CentOS team will update the main website and enable you to download the required image files. Unless the CentOS project states otherwise, you will only need to do this once, as all minor updates can be managed like any other operating system. However, if you do intend to download them again, then it is always a good idea to check the integrity of your image files with the md5sum checksum tool. Resources for Article: Further resources on this subject: The Economics of Open Source Donations [Article] Installing and Using Openfire [Article] Installing, Removing, and Upgrading Software [Article]
Read more
  • 0
  • 0
  • 2268

article-image-choosing-lync-2013-clients
Packt
25 Jul 2013
5 min read
Save for later

Choosing Lync 2013 Clients

Packt
25 Jul 2013
5 min read
(For more resources related to this topic, see here.) What clients are available? At the moment, we are writing a list that includes the following clients: Full client, as a part of Office 2013 Plus The Lync 2013 app for Windows 8 Lync 2013 for mobile devices The Lync Basic 2013 version A plugin is needed to enable Lync features on a virtual desktop. We need the full Lync 2013 client installation to allow Lync access to the user. Although they are not clients in the traditional sense of the word, our list must also include the following ones: The Microsoft Lync VDI 2013 plugin Lync Online (Office 365) Lync Web App Lync Phone Edition Legacy clients that are still supported (Lync 2010, Lync 2010 Attendant, and Lync 2010 Mobile) Full client (Office 2013) This is the most complete client available at the moment. It includes full support for voice, video, IM (similarly to the previous versions), and integration for the new features (for example, high-definition video, the gallery feature to see multiple video feeds at the same time, and chat room integration). In the following screenshot, we can see a tabbed conversation in Lync 2013: Its integration with Office implies that the group policies for Lync are now part of the Office group policy's administrative templates. We have to download the Office 2013 templates from the Microsoft site and install the package in order to use them (some of the settings are shown in the following screenshot): Lync is available with the Professional Plus version of Office 2013 (and with some Office 365 subscriptions). Lync 2013 app for Windows 8 The Lync 2013 app for Windows 8 (also called Lync Windows Store app) has been designed and optimized for devices with a touchscreen (with Windows 8 and Windows RT as operating systems). The app (as we can see in the following screenshot) is focused on images and pictures, so we have a tile for each contact we want in our favorites. The Lync Windows Store app supports contact management, conversations, and calls, but some features such as Persistent Chat and the advanced management of Enterprise Voice, are still an exclusive of the full client. Also, talking about conferencing, we will not be able to act as the presenter or manage other participants. The app is integrated with Windows 8, so we are able to use Search to look for Lync contacts (as shown in the following screenshot): Lync 2013 for mobile devices The Lync 2013 client for mobile devices is the solution Microsoft offers for the most common tablet and smartphone systems (excluding those tablets using Windows 8 and Windows RT with their dedicated app). It is available for Windows phones, iPad/iPhone, and for Android. The older version of this client was basically an IM application, and that is something that somehow limited the interest in the mobile versions of Lync. The 2013 version that we are talking about includes support for VOIP and video (using Wi-Fi networks and cellular data networks), meetings, and for voice mail. From an infrastructural point of view, enabling the new mobile client means to apply the Lync 2013 Cumulative Update 1 (CU1) on our Front End and Edge servers and publish a DNS record (lyncdiscover) on our public name servers. If we have had previous experience with Lync 2010 mobility, the difference is really noticeable. The lyncdiscover record must be pointed to the reverse proxy. Reverse proxy deployment requires for a product to be enabled to support Lync mobility, and a certificate with the lyncdiscover's public domain name needs to be included. Lync Basic 2013 version Lync Basic 2013 is a downloadable client that provides basic functionalities. It does not provide support for advanced call features, multiparty videos or galleries, and skill-based searches. Lync Basic 2013 is dedicated to companies with Lync 2013 on-premises, and it is for Office 365 customers that do not have the full client included with their subscription. A client will look really similar to the full one, but the display name on top is Lync Basic as we can see in the following screenshot: Microsoft Lync VDI 2013 plugin As we said before, the VDI plugin is not a client; it is software we need to install to enable Lync on virtual desktops based on the most used technologies, such as Microsoft RDS, VMware View, and XenDesktop. The main challenge of a VDI scenario is granting the same features and quality we expect from a deployment on a physical machine. The plugin uses "Media Redirection", so that audio and video originate and terminate on the plugin running on the thin client. The user is enabled to connect conferencing/telephony hardware (for example microphones, cams, and so on) to the local terminal and use the Lync 2013 client installed on the virtual desktop as it was running locally. The plugin is the only Lync software installed at the end-user workplace. The details of the deployment (Deploying the Lync VDI Plug-in ) are available at http://technet.microsoft.com/en-us/library/jj204683.aspx. Resources for Article : Further resources on this subject: Innovation of Communication and Information Technologies [Article] DPM Non-aware Windows Workload Protection [Article] Installing Microsoft Dynamics NAV [Article]
Read more
  • 0
  • 0
  • 6986

article-image-events
Packt
25 Jul 2013
2 min read
Save for later

Events

Packt
25 Jul 2013
2 min read
(For more resources related to this topic, see here.) What is a payload? The payload of an event, the event object, carries any necessary state from the producer to the consumer and is nothing but an instance of a Java class. An event object may not contain a type variable, such as <T>.   We can assign qualifiers to an event and thus distinguish an event from other events of an event object type. These qualifiers act like selectors, narrowing the set of events that will be observed for an event object type. There is no distinction between a qualifier of a bean type and that of an event, as they are both defined with @Qualifier. This commonality provides a distinct advantage when using qualifiers to distinguish between bean types, as those same qualifiers can be used to distinguish between events where those bean types are the event objects. An event qualifier is shown here: @Qualifier @Target( { FIELD, PARAMETER } ) @Retention( RUNTIME ) public @interface Removed {} How do I listen for an event? An event is consumed by an observer method , and we inform Weld that our method is used to observe an event by annotating a parameter of the method, the event parameter , with @Observes . The type of event parameter is the event type we want to observe, and we may specify qualifiers on the event parameter to narrow what events we want to observe. We may have an observer method for all events produced about a Book event type, as follows: public void onBookEvent(@Observes Book book) { ... } Or we may choose to only observe when a Book is removed, as follows: public void onBookRemoval(@Observes @Removed Book book) { ... } Any additional parameters on an observer method are treated as injection points. An observer method will receive an event to consume if: The observer method is present on a bean that is enabled within our application The event object is assignable to the event parameter type of the observer method
Read more
  • 0
  • 0
  • 1875

article-image-merchandising-success
Packt
25 Jul 2013
17 min read
Save for later

Merchandising for Success

Packt
25 Jul 2013
17 min read
(For more resources related to this topic, see here.) Shop categories Creating product categories, like most things in PrestaShop, is easy and we will cover that soon. First we need to plan the ideal category structure, and this demands a little thought. Planning your category structure You should think really hard about the following questions: What is your business key – general scope or specific? Remember, if the usability is complex for you, it will be difficult to get future customers. So what will make the navigation simple and intuitive for your customers? What structure will support any plan you might have for expanding the range in the future? What do your competitors use? What could you do to make your structure better for your customers than anybody else's? When you have worked it out, we will create the category structure and then we will create the content (images and descriptions) for your category pages. First you need to consider what categories you want for your product range. Here are some examples: If your business is geared to the general scope, then it could be something like: Books Electronics Home and garden Fashion, jewelry, and beauty However, if your business is a closed market, for example electronics, then it could be something like: Cameras and photography Mobile and home phones Sound and vision Video games and consoles You get the idea. My examples don't have categories, subcategories, or anything deeper just for the sake of it. There are no prizes for compartmentalizing. If you think a fairly fat structure is what your customer wants, then that is what you should do. If you are thinking, "Hang on, I don't have any categories let alone any subcategories," don't panic. If your research and common sense says you should only have a few categories without any subcategories, then stick to it. Simplicity is the most important thing. Pleasing your customer and making your shop intuitive for your customer will make you more money than obscure compartmentalizing of your products. Creating your categories Have your plan close at hand. Ideally, have it written down or, if it is very simple, have it clearly in your head. Enough of the theory, it is now time for action. Time for action – how to create product categories Make sure that you are logged into your PrestaShop back office. We will do this in two steps. First we will create your structure as per your plan, then in the next Time for action section, we will implement the category descriptions. Let's get on with the structure of your categories: Click on Catalog and you will see the categories. Click on one. Now click on the green + symbol to add a new subcategory. PrestaShop defines even your top-level categories as subcategories because the home category is considered to be the the top-level category. Just type in the title of your first main category. Don't worry about the other options. The descriptions are covered in a minute and the rest is to do with the search engines. You have created your first category. Now that you are back to the home category, you can click on the green button again to create your next main category. To do so, save as before and remember to check the Home radio button, when you are ready, to create your next main category. Repeat until all top-level categories are created. Have a quick look at your shop front to make sure you like what you see. Here is a screenshot from the PrestaShop demo store: Now for the subcategories. We will create one level at a time as earlier. So we will create all the subcategories before creating any categories within subcategories. In your home category, you will have a list of your main categories. Click on the first one in the list that requires a subcategory. Now click on the create subcategory + icon. Type the name of your subcategory, leaving the other options, and click on Save. Go back to the main category if you want to create another subcategory. Play around with clicking in and out of categories and subcategories until you get used to how PrestaShop works. It isn't complicated, but it is easy to get lost and start creating stuff in the wrong place. If this happened to you, just click on the bin icon to delete your mistake. Then pay close attention to the category or subcategory you are in and carry on. You can edit the category order from the main catalog page by selecting the box of the category you want to move and then clicking an up or down arrow. Finish creating your full category structure. Play with the category and subcategory links on your shop front to see how they work and then move on. What just happened? Superb! Your category structure is done and you should be fairly familiar with navigating around your categories in your control panel. Now we can add the category and subcategory descriptions. I left it empty until now because as you might have noticed, the category creation palaver can be a bit fiddly and it makes sense to keep it as straightforward as possible. Here are some tips for writing good category descriptions followed by a quick Time for action section for entering descriptions into the category itself. Creating content for your categories and subcategories I see so many shops online with really dull category descriptions. Category descriptions should obviously describe but they should also sell! Here are a few tips for writing some enticing descriptions: Keep them short—two paragraphs at the most. People do not visit your website to read. The detail should be in the products themselves. Similar to a USP, category descriptions should be a combination of fact and emotive description that focuses on the benefit to the customer. Try and be as specific as you can about each category and subcategory so that each description is accurate and relevant in its own right. For example, don't let the category steal all the glory from a subcategory. It is very important for SEO. Time for action – adding category descriptions Be ready with the text for all your categories or you can, of course, type them as you go: Go to Catalog and then on the first categories' Edit button. Enter your category description and click on Save. Click on the subcategories of your first category. Then enter and save a description for each (if any). Navigate to the second main category and enter a description. Repeat the same for each of the subcategories in turn. Reiterate the preceding steps for each category. What just happened? You now have a fully functioning category structure. Now we can go on to look at adding some of your products. Adding products Click on the Catalog tab and then click on product. It is pretty similar to category. In the Time for action section, I will cover what to enter in each box as a separate item. However, I will skip over a few items like meta tags because they are best dealt with on a site-wide basis separately. The other important option is the product description. This deserves special treatment because it needs to be effective at selling your product. With the categories, I specifically showed you how to create the structure before filling in the descriptions because I know others who have got into a muddle in the past. It is less likely, but still possible, to get into a bit of a muddle with the products as well. This is especially true if you have lots of them. Perhaps you should be the judge of whether to fill in your catalog before adding descriptions or add descriptions as you go. So here is a handy guide to create great product descriptions. It will help you to decide whether you should fill product descriptions at the same time as the rest of the details, or whether you should just enter the product title and revisit them later to fill in the rest of the details. Product descriptions that sell Don't fall into the trap of simply describing your products. It might be true that a potential customer does need to know the dry facts like sizes and other uninspiring information, but don't put this information in the brief description or description boxes. PrestaShop provides a place for bare facts—the Features tab (there will be more on this soon). The brief description and description boxes that will be described in more detail soon are there to sell to your customers —to increase their interest to a level that makes them "want" the product. It actually suggests they pop it in their cart and buy it. The way you do this is with a very simple and age-old formula that actually works. And,of course, having whetted your appetite, it would be rude not to tell you about it. So here it goes. Actually selling the product Don't just tell your customers about your product, sell them the product. Explain to them why they should buy it! Use the FAB technique—feature, advantage, benefit: Tell the customer about a feature: This teddy bear is made from a new fiber and wool mix This laptop has the brand new i7 processor made by Intel This guide was written by somebody who has survived cancer And the advantage that feature gives them: So it is really, really soft and fluffy! i7 is the very first processor series with a DDR3 integrated memory controller! So all the information and advice is real and practical Then emphasize the real emotive benefit this gives them: Which means your little boy or girl is going to feel safe, loved, and secure with this wonderful bear Meaning that this laptop gives your applications, up to a 30 percent performance boost over every other processor series ever made Giving you or your loved one the very best chance of beating with cancer and having more precious time they have with the people they love Don't just stop at one feature. Highlight the most important features. By most important features, of course I mean the features that lead to the best most emotive and personal benefits. Not too many though. If your product has loads of benefits, then try and pick just the best ones. Three is perfect. Three really is a magic number. All the best things come in threes and scientific research actually proves that thoughts or ideas presented in threes influence human emotion the most. If you must have more than three features, summarize them in a quick bulleted list. Three is good: Soft, strong, and very long Peace, love, and understanding Relieves pain, and clears your nose without drowsiness Ask for the sale When you have used the FAB technique, ask the customer to part with their money! Say something like, "Select the most suitable option for you and click on Add to cart" or "Remember that abc is the only xyz with benefit 1, benefit 2, and benefit 3.Order yours now!" Create some images with GIMP If you have a favorite photo editor then great. If you haven't, then I suggest you use GIMP. It's cool, easy, and free: www.gimp.org. Time for action – how to add a product to PrestaShop Let's add some products: Click on catalog and then click on product. Click on the Add a new product link. You will see the following screenshots. Okay, I admit it. It does look a little bit daunting. But actually it is not that difficult. Much of it is optional, and even more we will revisit after further discussion. So don't despair. There is a table of explanations for you after the screenshots. Field Explanation Name The short name/description of your product. There is a brief description and a full description box later, but perhaps a bit more than a short name should go here. For example, 50 cm golden teddy bear-extra fluffy version. Status Choose Enabled or Disabled. If your product is for sale as soon as you're open, click Enabled. If your product is discontinued or needs to be removed from sale for any reason, click Disabled. Reference An optional unique reference for your product. For example, 50cmFT - xfluff. EAN13 The European Article Number or barcode. If your product has one (and almost everything does), use it because some people use this for searching or identifying a product. Jan The Japanese Article Number or barcode. If your product has one (and almost everything does), use it because some people use this for searching or identifying a product. UPC The USA and Canadian Article Number or barcode. If your product has one (and almost everything does), use it because some people use this for searching or identifying a product. Visibility If you want to show the item on the catalog, only on the search or everywhere. Type You can chose if there is a physical product, pack, or a downloadable product. Options To make the product available/unavailable to order. To show or hide the price. To enable/disable the online message. Condition If the item is brand new, second hand, or refurbished. Short description Here you need to add a brief description about the item. This text will be shown on the catalog. Description When a customer clicks on the item, he will read this text. Tags Leave blank for now. Fill in your product page as described previously. Click on the Images tab at the top of the product page. Browse to the image you created earlier and upload it. Note that PrestaShop will compress the image for you. It is worth having a look at the final image and maybe varying the amount (if any) that you apply when creating your product images. Click on Save and then go and admire your product in your store front. Repeat until all your products are done, but don't forget to check how things look from the customer's point of view. Visit the category and product pages to check whether things are like the way you had expected them to be. If you have a huge range that is going to take you a long time, then consider just entering your key products. Proceed with this to get the money coming in and add the rest of your range in a bit over the course of time. What just happened? Now you have something to actually sell, let's go and showcase some of your products. Here is how to make some of your products stand out from the crowd. Highlighting products Next is a list of the different ways to promote elements of your range. There is also an explanation of each option and how to do it, as well. New products So you have just found some great new products. How do you let your visitors know about it? You could put an announcement on your front page. But what if a potential customer doesn't visit your front page or perhaps misses the announcement? Welcome to the new products module. Time for action – how to highlight your newest products The following are the quick steps to enable and configure the highlighting of any new products you add. Once this is set up, it will happen automatically, now and in the future. Click on the Modules tab and scroll down to the New products block module. Click on Install. Scroll back down to the module you just installed and click on Configure. Choose a number of products to be showcased and click on Save. Don't forget to have a look at your shop front to see how it works. Click around a few different pages and see how the highlighted product alternates. What just happened? Now you are done with new products and they will never go unnoticed. Specials Special refers to the price. This is the traditional special offer that customers know and love. Time for action – creating a special offer The following steps help us create special offers and make sure they will never go unnoticed: Click on the Catalog tab and navigate to the category or subcategory that contains the product you want to make available as a special offer. Click on the Products to go to its details page. Click on Prices and go to the Specific prices section. Click on Add a new specific price. You can enter an actual monetary amount in the first box or a percentage in the second box. Monetary amounts work well for individual discounts and percentages work well as part of a wider sale. But this is not a hard-and-fast rule. So choose what you think your customers might prefer. Click on Save. Now go and have a look at the category that the product is in and click on the product as well. You'll notice the smart enticing manner that PrestaShop uses to highlight the offer. You can have as many or as few special offers as you like. But what if you wanted to really push a product offer or a wider sale? Yes, you guessed it, there's a module. Click on the Modules tab and scroll down to Specials block and click on Install. Getting the hang of this? Thought so. Go and have a look at the effect on your store. What just happened? Your first sale is underway. Recently viewed What's this then? When customers browse products, they forget what they have seen or how to find it again. By prominently displaying a module with their most recent viewings, they can comfortably click back and forth comparing until they have made a buying decision. Now you don't need me to tell you how to set this up. Go to the module, switch it on, and you're done. Best sellers This is just what it says. Not necessarily an offer or anything else is special about it. But if it sells, well there must be something worth talking about it. Install the best sellers module in the usual place to highlight these items. Accessories I love accessories. It's all about add-on sales. Ever been to a shop to buy a single item and come out with several? Electrical retailers are brilliant at this. Go in for a PC and come out with a printer, scanner, camera, ink, paper, and the list goes on. Is it because their customers are stupid? Of course they are not! It is because they offer compelling or essential accessories that are relevant to the sale. By creating accessories, you will get a new tab at the bottom of each relevant product page along with PrestaShop making suggestions at key points of the sale. All we have to do is tell PrestaShop what is an accessory to our various products and PrestaShop will do the rest. Time for action – creating an accessory Accessories are products. So any product can be an accessory of any other product. All you have to do is decide what is relevant to what. Just think about appropriate accessories for your products and read on. The quick guide for creating accessories are as follows: Click on the Catalog tab, then click on product. Find the product you think should have some accessories. Click on it to edit it by navigating to Associations on the page and find the Accessories section, as shown in the following screenshot: Find the product that you wish to be an accessory by typing the first letters of the product name and selecting it. Save your amended product. You can add as many accessories to each product as you like. Go and have a look at your product on your shop front and notice the Accessories tab. What just happened? You just learned how to accessorize. It's silly not to accessorize, not because it costs you nothing, but because a few clicks could significantly increase your turnover. Now we can go on to explore more product ideas.
Read more
  • 0
  • 0
  • 1893
article-image-material-nodes-cycles
Packt
25 Jul 2013
12 min read
Save for later

Material nodes in Cycles

Packt
25 Jul 2013
12 min read
(For more resources related to this topic, see here.) Getting Ready In the description of the following steps, I'll assume that you are starting with a brand new Blender with the default factory settings; if not, start Blender and just click on the File menu item to the top main header bar to select Load Factory Settings from the pop-up menu. In the upper menu bar, switch from Blender Render to Cycles Render (hovering with the mouse on this button shows the Engine to use for rendering label). Now split the 3D view into two horizontal rows and change the upper one in to the Node Editor window by selecting the menu item from the Editor type button at the left-hand corner of the bottom bar of the window itself. The Node Editor window is, in fact, the window we will use to build our shader by mixing the nodes (it's not the only way, actually, but we'll see this later). Put the mouse cursor in the 3D view and add a plane under the cube (press Shift + A and navigate to Mesh | Plane). Enter edit mode (press Tab), scale it 3.5 times bigger (press S, digit 3.5, and hit Enter) and go out of edit mode (press Tab). Now, move the plane one Blender unit down (press G, then Z, digit -1, and then hit Enter). Go to the little icon (Viewport Shading) showing a sphere in the bottom bar of the 3D view and click on it. A menu showing different options appears (Bounding Box, Wireframe, Solid, Texture, Material, and Rendered). Select Rendered from the top of the list and watch your cube being rendered in real time in the 3D viewport. Now, you can rotate or/and translate the view or the cube itself and the view gets updated in real time (the speed of the update is only restricted by the complexity of the scene and by the computing power of your CPU or of your graphic card). Let's learn more about this: Select Lamp in the Outliner (by default, a Point lamp). Go to the Object Data window under the Properties panel on the right-hand side of the interface. Under the Nodes tab, click on Use Nodes to activate a node system for the selected light in the scene; this node system is made by an Emission closure connected to a Lamp Output node. Go to the Strength item, which is set to 100.000 by default, and start to increase the value—as the intensity of the Lamp increases, you can see the cube and the plane rendered in the viewport getting more and more bright, as shown in the following screenshot: How to do it... We just prepared the scene and had a first look at one of the more appreciated features of Cycles: the real-time rendered preview. Now let's start with the object's materials: Select the cube to assign the shader to, by left-clicking on the item in the Outliner, or also by right-clicking directly on the object in the Rendered viewport (but be aware that in Rendered mode, the object selection outline usually around the mesh is not visible because, obviously, it's not renderable). Go to the Material window under the Properties panel: even if with the default Factory Settings selected, the cube has already a default material assigned (as you can precisely see by navigating to Properties | Material | Surface). In any case, you need to click on the Use Nodes button under the Surface tab to activate the node system; or else, by checking the Use Nodes box in the header of the Node Editor window. As you check the Use Nodes box, the content of the Surface tab changes showing that a Diffuse BSDF shader has been assigned to the cube and that, accordingly, two linked nodes have appeared inside the Node Editor window: the Diffuse BSDF shader itself is already connected to the Surface input socket of a Material Output node (the Volume input socket does nothing at the moment, it's there in anticipation of a volumetric feature on the to-do list, and we'll see the Displacement socket later). Put the mouse cursor in the Node Editor window and by scrolling the mouse wheel, zoom in to the Diffuse BSDF node. Left-click on the Color rectangle: a color wheel appears, where you can select a new color to change the shader color by clicking on the wheel or by inserting the RGB values (and take note that there are also a color sampler and the Alpha channel value, although the latter, in this case, doesn't have any visible effect on the object material's color): The cube rendered in the 3D preview changes its material's color in real time. You can even move the cursor in the color wheel and watch the rendered object switching the colors accordingly. Set the object's color to a greenish color by setting its RGB values to 0.430, 0.800, and 0.499 respectively. Go to the Material window and, under the Surface tab, click on the Surface button, which at the moment is showing the Diffuse BSDF item. From the pop-up menu, select the Glossy BSDF shader item. The node now also changes in the Node Editor window and so does accordingly the cube's material in the Rendered preview, as shown here: Note that although we just switched a shader node with a different one, the color we set in the former one has been kept also in the new one; actually, this happens for all the values that can be kept from one node to a different one. Now, because in the real world a material having a 100 percent matte or reflective surface could hardly exist, a more correct basic Cycles material should be made by mixing the Diffuse BSDF and the Glossy BSDF shaders blended together by a Mix Shader node, in turn connected to the Material Output node. In the Material window, under the Surface tab, click again on the Surface button that is now showing the Glossy BSDF item and replace it back with a Diffuse BSDF shader. Put the mouse pointer in the Node Editor window and, by pressing Shift + A on the keyboard, make a pop-up menu appear with several items. Move the mouse pointer on the Shader item, it shows one more pop-up where all the shader options are collected. Select one of these shader menu items, for example, the Glossy BSDF item. The shader node is now added to the Node Editor window, although not connected to anything yet (in fact, it's not visible in the Material window but is visible only in the Node Editor window); the new nodes appear already selected. Again press Shift + A in the Node Editor window and this time add a Mix Shader node. Press G to move it on the link connecting the Diffuse BSDF node to the Material Output node (you'll probably need to first adjust the position of the two nodes to make room between them). The Mix Shader node gets automatically pasted in between, the Diffuse node output connected to the first Shader input socket, as shown in the following screenshot: Left-click with the mouse on the green dot output of the Glossy BSDF shader node and grab the link to the second input socket of the Mix Shader node. Release the mouse button now and see the nodes being connected. Because the blending Fac (factor) value of the Mix Shader node is set by default to 0.500, the two shader components, Diffuse and Glossy, are now showing on the cube's surface in equal parts, that is, each one at 50 percent. Left-click on the Fac slider with the mouse and slide it to 0.000. The cube's surface is now showing only the Diffuse component, because the Diffuse BSDF shader is connected to the first Shader input socket that is corresponding to a value set to 0.000. Slide the Fac slider value to 1.000 and the surface is now showing only the Glossy BSDF shader component, which is, in fact, connected to the second Shader input socket corresponding to a value set to 1.000. Set the Fac value to 0.800. The cube is now reflecting on its sides, even if blurred, the white plane, because we have a material that is reflective at 80 percent, matte at 20 percent, and so on: Lastly, select the plane, go to the Material window and click on the New button to assign a default whitish material. How it works... So, in its minimal form, a Cycles material is made by a closure (a node shader) connected to the Material Output node; by default, for a new material, the node shader is the Diffuse BSDF with RGB color set to 0.800, and the result is a matte whitish material (with the Roughness value at 0.000 actually corresponding to a Lambert shader). The Diffuse BSDF node can be replaced by any other one of the available shader list. For example, by a Glossy BSDF shader as in the former cube scene, which produces a totally mirrored surface material. As we have seen, the Node Editor window is not the only way to build the materials; in the Properties panel on the right-hand side of the UI, we have access to the Material window, which is usually divided as follows: The material name, user, and the datablock tab The Surface tab, including in a vertical ordered column only the shader nodes added in the Node Editor window and already connected to each other The Displacement tab, which we'll see later The Settings tab, where we can set the object color as seen in the viewport in not-rendered mode (Viewport Color), the material Pass Index, and a Multiple Importance Sample option The Material window not only reflects what we do in the Node Editor window and changes accordingly to it (and vice versa), but also can be used to change the values, to easily switch the closures themselves and to some extent to connect them to the other nodes. The Material and the Node Editor windows are so mutual that there is no prevalence in which one to use to build a material; both can be used individually or combined, depending on preferences or practical utility. In some cases, it can be very handy to switch a shader from the Surface tab under Material on the right (or a texture from the Texture window as well, but we'll see textures later), leaving untouched all the settings and the links in the node's network. There is no question, by the way, that the Material window can become pretty complex and confusing as a material network grows more and more in complexity, while the graphic appearance of the Node Editor window shows the same network in a much more clear and comprehensible way. There's more... Looking at the Rendered viewport, you'll notice that the image is now quite noisy and that there are white dots in certain areas of the image; these are the infamous fireflies, caused mainly by transparent, luminescent, or glossy surfaces. Actually, they have been introduced in our render by the glossy component. Follow these steps to avoid them: Go to the Render window under the Properties panel. In the Sampling tab, set Samples to 100 both for Preview and Render (they are set to 10 by default). Set the Clamp value to 1.00 (it's set to 0.00 by default). Go to the Light Paths tab and set the Filter Glossy value to 1.00 as well. The resulting rendered image, as shown here, is now a lot more smooth and noise free: Save the blend file in an appropriate location on your hard drive with a name such as start_01.blend. Samples set to 10 by default are obviously not enough to give a noiseless image, but are good for a fast preview. We could also let the Preview samples as default and increase only the Render value, to have longer rendering times but a clean image only for the final render (that can be started, as in BI, by pressing the F12 key). By using the Clamp value, we can cut the energy of the light. Internally, Blender converts the image color space to linear. It then re-converts it to RGB, that is, from 0 to 255 for the output. A value of 1.00 in linear space means that all the image values are now included inside a range starting from 0 and arriving to a maximum of 1, and that values bigger than 1 are not possible, so usually avoiding the fireflies problem. Clamp values higher than 1.00 can start to lower the general lighting intensity of the scene. The Filter Glossy value is exactly what the name says, a filter that blurs the glossy reflections on the surface to reduce noise. Be aware that even with the same samples, the Rendered preview not always has a total correspondence to the final render, both with regards to the noise as well as to the fireflies. This is mainly due to the fact that the preview-rendered 3D window and the final rendered image usually have very different sizes, and artifacts visible in the final rendered image may not show in a smaller preview-rendered window. Summary In this article we learned how to build a basic Cycles material, add textures, and use lamps or light-emitting objects. Also, we learned how to successfully create a simple scene. Resources for Article: Further resources on this subject: Advanced Effects using Blender Particle System [Article] Learn Baking in Blender [Article] Character Head Modeling in Blender: Part 2 [Article]
Read more
  • 0
  • 0
  • 3621

article-image-introducing-rubymotion-and-hello-world-app
Packt
22 Jul 2013
7 min read
Save for later

Introducing RubyMotion and the Hello World app

Packt
22 Jul 2013
7 min read
(For more resources related to this topic, see here.) If you're reading this, you're either searching for an understanding of how RubyMotion can give you the keys to make iPhone, iPad, and OS X applications, or you're simply looking for further depth in your understanding of Ruby and Objective-C development. Either way, you're in the right place. To start this journey, we need to understand the basics of these two respected, but philosophically dissimilar, technologies and how a path has been beaten between them. Starting at the base, Apple development for iOS has traditionally been handled in Objective-C. Though Apple products have grown in popularity, Objective-C has not always been the first choice for application development. There's a long and torturous road of developers who have given up their app ambitions because of Objective-C. It is clear that for the greater part of over two decades, Objective-C has generally been the only programming language choice available for apps with Apple. Objective-C was made popular by Steve Jobs' company NeXT, for licensing Objective-C from StepStone in 1988. You'll often see evidence of this in the naming conventions of fundamental objects prefixed with NS for NeXTStep/Sun. This history renders the language a business decision as much as it was ever a developer-based decision. At the time Objective-C was licensed, the Ruby programming language was just an unnamed idea in Matz's head (Yukihiro "Matz" Matsumoto, inventor of Ruby). Objective-C has evolved, grown, and survived the test of time, but it ultimately remains verbose, without standardization, and programmatically rigid. In today's world, developers can afford to be opinionated with their programming language preferences, and a lot of them choose Ruby. Ruby is a standardized, dynamic, and general object-oriented programming language that takes inspiration from a long list of successful languages. Ruby is known to support a myriad of programming paradigms and is especially known for yielding elegant code. It's also often the cool programming language. Compared to the verbose and explicit nature of Objective-C, Ruby is a far cry and extremely opinionated language that programmers often adore. Let's take a moment to identify some core differences in the syntax of these two programming languages, starting with Objective-C. Objective-C is strongly typed. Counter to what some believe, strongly typed doesn't mean you hit the keys really hard, it means your variables have restrictions in their data types and how those variables can intermix. In Objective-C this is strictly checked and handled at compile time by a .hfile, the end result being that you're usually managing at least two files to make changes in one. Though you'll often find Objective-C methods to be long and capitalized in CamelCase, Ruby clashes with a Python-styled lowercase brevity. For example: Objective-C styled method SomeObject.performSomeMethodHere Ruby styled method SomeObject.some_method It's by no accident that I've shortened the method name in the preceding example. It's actually quite common for Objective-C to have long-winded method names, while, conversely Ruby methods are to be as short as possible, while maintaining the general intention of the method. Additionally, Ruby is more likely to sample functional and meta-programming aspects to make applications simple. So, if you're wondering which of these paradigms you will need to use and be accustomed to, the answer is both! I've seen a lot of RubyMotion code, and some people simply abandon their Ruby ways to try and make their code fit in with Objective-C libraries, all with great haste. But by far, the best method I've seen, and I highly recommend, is a mix. All Objective-C and Cocoa foundation framework objects should remain CamelCase, while all Ruby remains snake_case. At first glance this seems like twice the work, but it's really next to no effort at all, as your custom objects will be all written in Ruby by you. The advantage here is that upon examination, you can tell if a function, object, or variable should be looked up online on the Apple developer site (http://developer.apple.com/library/ios/navigation/) or if it should be searched for in a local code or Ruby code (http://www.ruby-doc.org/). I kind of wish I had this benefit with other Ruby languages, since I can instantly return to an older project and distinguish which code is purely mine and which is framework. Another key diff erence is the translation of code from messages to parameterized styling. I'm going to use some of the examples from RubyMotion.com to elaborate this issue. To properly convert the Objective-C: [string drawAtPoint:point withFont:font]; You will have to simply slide everything down to the left. The parameter to string is a method on it, and the rest become parameters. This yields the following code: string.drawAtPoint(point, withFont:font) Let's start with our Hello World app now. Have the controller in place so we can break away from the lifeless shell application and move more toward a true "Hello World" app. We won't need to deal with the AppDelegateany longer. Now we can start placing code in our controller. Remember when I said that this is a framework that calls into our code at given points, here's where we choose one of those points in time to hook into, and we'll choose one of the most common UIViewControllermethods, viewDidLoad. So, create a method called viewDidLoad, and let's put the following code inside: To find out what delegates are supported by any method and the order of method calls, you can look up the class reference of the object you are extending. For example, the documentation on the UIViewControllerclass' viewDidLoadcall is identified at http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html. Running your application at this point (by typing rakein the console) will cause your application to output "Hello World" to the application's standard output (the command line in this case). There's nothing too special happening here, we're using the traditional Ruby putsmethod to give us some feedback on the console. Running this does start the simulator. To quit the simulator, you can use command+ Q or from the console window, press Ctrl+ Dor Ctrl+ C. Since our phone doesn't really have a console to receive the standard output message, let's take this up a notch by adding a label to the application and configuring it to be a more traditional Hello World" on the device. So, we plan on making a label that will have the text "Hello World", correct? Let's create the test for that. We'll start by making a new file in our specfolder called hello_world_controller_spec.rband we'll make it look like the following: Let's inspect the testing code from the previous image. Everything looks similar to the other code but, as you can see, there's no need to make a beforeblock, since we are able to access the controller by simply stating the controller we're testing on the second line. This shortcut works for any ViewController you're testing! The actual testing and use for the variable starts with our specification. We grab the label so we can apply our two requirements on the following lines. We check the text value, and verify that the label has been added to the view. This might seem quite nebulous without knowing what we're testing, but the logic is simple. We want to make sure there's a label that says "Hello World" and we want it to be visible. Running these tests will fail, which puts us on track to write the actual "Hello World" portion. You should add the following code to your project's hello_world_controller.rbfile: Summary There it is! We've finally written a real Hello World application! Congratulations on your first RubyMotion application! You deserve it! Resources for Article : Further resources on this subject: Integrating Solr: Ruby on Rails Integration [Article] Building tiny Web-applications in Ruby using Sinatra [Article] Getting started with using Chef [Article]
Read more
  • 0
  • 0
  • 3568

article-image-microsoft-dynamics-crm-2011-overview
Packt
22 Jul 2013
10 min read
Save for later

Microsoft Dynamics CRM 2011 Overview

Packt
22 Jul 2013
10 min read
(For more resources related to this topic, see here.) Introduction to CRM 2011 Every organization is dependent on customers, and every organization is challenged to manage these customers. Businesses need a way to attract, sell to, service, and track every interaction these customers have with their organization. To do so, they often implement a Customer Relationship Management (CRM) system. Microsoft offers a CRM solution as part of their Dynamics suite, which allows companies to implement a system that manages more than just their customers. Microsoft Dynamics CRM is a web-based application that can be accessed online through an Internet browser or through Microsoft Office Outlook. Microsoft Dynamics CRM 2011 Web client Microsoft Dynamics CRM 2011 Outlook client Microsoft Dynamics CRM includes three main modules: Sales Marketing Customer service Each module contains entities, which are objects in CRM, and are used to help model data. Throughout this article, business examples will be used to explain various concepts. A fictitious company called Race2Win Insurance Company will be used to further illustrate these concepts. Sales module Microsoft Dynamics CRM allows businesses to optimize their sales processes and customer tracking efforts. With CRM, an organization can increase interactions with current customers, shorten sales cycles, and increase opportunity close rates to gain new customers. The sales module within CRM consists of the following entities: Leads Accounts Contacts Opportunities Marketing lists Products Sales literature Quotes Orders Invoices Competitors Quick campaigns Goals Goal metrics Rollup queries Each of these entities are explained in more detail further, but let's give a high-level overview of how users could potentially use these out of the box capabilities. Business scenarios The business scenarios that we'll cover in a moment outlines the use of the sales module for our fictitious insurance company. Although entities such as marketing lists, quick campaigns, and sales literature are found in the sales module, these will be discussed in the marketing business scenarios. For our scenarios, we'll illustrate examples from the viewpoint of various individual roles within the organization. Leads Race2Win Insurance Company needs a way to track leads they've acquired as a result of efforts by their marketing team. Microsoft Dynamics CRM allows the company to track and qualify leads. For example, let's say Race2Win is capturing information on the lead record related to a potential insurance customer. Based on information entered, business rules can be applied to categorize the lead as hot, warm, or cold. CRM has out of the box functionality to apply these business rules automatically. Once a lead is qualified, Dynamics CRM provides the ability to convert the lead into an opportunity, account, contact, or a combination of the three. Accounts The organizations or companies that Race2Win Insurance views as customers can be tracked as accounts in CRM. These accounts may be managed by one or more salespeople. A salesperson may receive commission on sales made to their managed accounts, thus making accounts critical. Accounts contain the address, industry, and various other demographic data about the customer. Contacts As part of the sales process, Race2Win Insurance Company's sales force may reach out to individuals or employees at a company. Individuals, either on their own or tied to a company, can be tracked as contacts in Microsoft Dynamics CRM. Like the account, contact records can store addresses and industry/professional information, but can also store more personal data, such as birthdays, anniversaries, and information about various family members. A salesperson may find personal information critical to start and maintain a personal relationship with people at a company. Opportunities Opportunities can allow the Race2Win sales force to track potential sales opportunities with their customers. The opportunities can go through various sales cycles, and can track the estimated versus actual revenue of a particular sale. Opportunities can have products from the product catalog associated to them in order to help estimate the revenue more accurately. The Race2Win Insurance salespeople receive their commission when an opportunity is won, and the commission amount is based on the estimated revenue. Products Race2Win Insurance Company has various insurance products and services it may sell. Products can be sold to different customers at different prices, and some products may be eligible for discounts based on the quantity ordered. Dynamics CRM allows all of the above functionality through the use of the product catalog. Quotes Let's say that during the course of a sales cycle, the customer wishes to receive more detailed pricing information such as an estimate from the Race2Win salesperson. Dynamics CRM allows a quote to be generated ad hoc or from an opportunity. In either case, products from the product catalog can be added, prices from the price list can be used, and discounts can be applied—all to create an accurate quote. Orders If a customer wishes to proceed with purchasing products or services, the opportunity can be closed as won. The salesperson will receive commission, and the process is now handed off to someone in order entry to create an order. Orders can be created ad hoc, from an opportunity, or quote. If an opportunity or quote has products, prices, and/or discounts, these can be inherited, making the generation of the order timely and accurate. Invoices An invoice can be generated for a customer in place of an order if needed. Many other organizations like Race2Win have their billing department typically create an invoice once the order is ready to be billed. An invoice can be created ad hoc or from an opportunity, quote, or order. Like an order, invoices can inherit the products, prices, and/or discounts from an opportunity, quote, or order. While quotes, orders, and invoices can be created in Microsoft Dynamics CRM, sometimes they are created in an ERP system and then imported into Dynamics CRM for reference or reporting. Competitors Race2Win Insurance Company has now been using the leads generated to attain new customers, increase sales, and generate quotes, orders, and invoices for customers quickly and efficiently. Like any successful organization, Race2Win has to deal with competition. Dynamics CRM gives the organization's sales force and management the ability to track competitors, analyze their sales strategies, products, and the business they win. Goals Throughout a period of time, say fiscal year, an organization like Race2Win can set up goals to track various metrics such as sales performance. These goals can be tracked for each individual, and managers have the ability to see each of their team member's goals. The entire business scenario we just outlined can be achieved by using the Microsoft Dynamics CRM sales module. Marketing module Microsoft Dynamics CRM allows an organization to launch and maintain marketing campaigns. The responses to a campaign can be tracked to gauge the effectiveness of a campaign. These responses can also be converted into accounts, contacts, leads, quotes, orders, or opportunities. The Dynamics CRM marketing module consists of the following entities: Leads Accounts Contacts Marketing lists Campaigns Quick campaigns Sales literature Products Each of these entities are explained in more detail further, but let's again look at a high-level overview. Business scenario The business scenarios that we'll cover in a moment outlines the use of the marketing module using our fictitious company, Race2Win Insurance Company. Race2Win's marketing team has analyzed its existing customer base and found areas to expand the company's business. They can market new products and services to their existing customer base, and try and turn potential customers into new ones. Marketing lists Race2Win has realized that it needs to market new insurance products to an existing list of accounts, and market existing products to potential customers in China. Microsoft Dynamics CRM allows Race2Win to set up a marketing list containing a static list of accounts. They can also use CRM to set up a dynamic marketing list of all leads where the address has the country set to China. Campaigns Using marketing lists, an organization can kick off, run, and evaluate marketing campaigns. Race2Win can kick off a campaign very quickly for the existing accounts and it can also execute a more lengthy campaign, containing multiple communication channels, for the leads in China. Depending on the campaign type, the marketing team can create planning activities, track the cost of the campaign,and target certain products. Sales literature At times, customers or even internal business users may want to know more about a product that an organization is selling or marketing. Race2Win is no different, dealing with multiple inquiries about products from customers on a weekly basis. The sales literature in CRM can offer collateral for marketing or sales teams to share. An example can be a brochure of their latest insurance products. The scenarios we just described illustrates how the Microsoft Dynamics CRM marketing module can be used to achieve any marketing goal. Customer service module Obtaining new customers is an important goal of any organization, but servicing existing customers is just as important. Microsoft Dynamics CRM offers a solution to service an organization's customers, manage service resources, and maintain a knowledge base repository that can be used to efficiently resolve future service incidents. The Dynamics CRM service module consists of the following entities: Cases Service calendar Accounts Contacts Knowledge base article Contracts Products Goals Goal metrics Rollup queries Each of these entities are explained in more detail further, but let's look at a high-level overview of how an organization could potentially use these out of the box capabilities. Business scenarios Thanks to CRM, Race2Win Insurance Company has been able to effectively market and sell its products to companies in a wide range of industries all over the world. Now it's time for Race2Win to start servicing their clients, and it's Dynamics CRM to the rescue once again. Cases Let us say a customer didn't receive their invoice for insurance products that they purchased. This customer e-mails this issue to a client service representative at Race2Win. With Dynamics CRM, this e-mail can be converted to a case. During that process of conversion, an account or contact can be linked (the case can reference a product if needed). Once converted, the original e-mail will be tied to the newly opened case. After the case is created, it can be assigned to a user, or routed to a queue. Throughout its lifecycle, activities such as e-mails, phone calls, and/or tasks can be tracked as a part of the case. Knowledge base articles In trying to resolve the case, users can access a repository of knowledge base articles to reference past issues and resolutions. Contracts Race2Win can use CRM to create service contracts to defne the type and level of support required. These contracts can then be referenced when new cases are opened. Service calendar If the servicing of customers requires the allocation of resources, whether that is an individual employee, a contractor, a facility or equipment, Dynamics CRM's scheduling features can assist. The service calendar can show users how each resource is being allocated for a given time period. With this knowledge, you can schedule resources more efficiently in order to deliver a prompt resolution to a case. As you can see, CRM has a rich feature set that can be used to service any type of client. We just went through a high-level introduction of the three main modules in Microsoft Dynamics CRM. This article is a guide to help pass the CRM 2011 Applications exam (MB2-868) and we will delve deeper into each of the modules to help you better understand the application. The next section gives you an introduction to Microsoft Dynamics CRM 2011 training and certifications.
Read more
  • 0
  • 0
  • 2370
article-image-vaadin-project-spring-and-handling-login-spring
Packt
22 Jul 2013
16 min read
Save for later

Vaadin project with Spring and Handling login with Spring

Packt
22 Jul 2013
16 min read
(For more resources related to this topic, see here.) Setting up a Vaadin project with Spring in Maven We will set up a new Maven project for Vaadin application that will use the Spring framework. We will use a Java annotation-driven approach for Spring configuration instead of XML configuration files. This means that we will eliminate the usage of XML to the necessary minimum (for XML fans, don't worry there will be still enough XML to edit). In this recipe, we will set up a Spring project where we define a bean that will be obtainable from the Spring application context in the Vaadin code. As the final result, we will greet a lady named Adela, so we display Hi Adela! text on the screen. The brilliant thing about this is that we get the greeting text from the bean that we define via Spring. Getting ready First, we create a new Maven project. mvn archetype:generate -DarchetypeGroupId=com.vaadin -DarchetypeArtifactId=vaadin-archetype-application -DarchetypeVersion=LATEST -Dpackaging=war -DgroupId=com.packtpub.vaadin -DartifactId=vaadin-with-spring -Dversion=1.0 More information about Maven and Vaadin can be found at https://vaadin.com/book/-/page/getting-started.maven.html. How to do it... Carry out the following steps, in order to set up a Vaadin project with Spring in Maven: First, we need to add the necessary dependencies. Just add the following Maven dependencies into the pom.xml file: dependencies into the pom.xml file: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> In the preceding code, we are referring to the spring.version property. Make sure we have added the Spring version inside the properties tag in the pom.xml file. <properties> … <spring.version>3.1.2.RELEASE</spring.version> </properties> At the time of writing, the latest version of Spring was 3.1.2. Check the latest version of the Spring framework at http://www.springsource.org/spring-framework. The last step in the Maven configuration file is to add the new repository into pom.xml. Maven needs to know where to download the Spring dependencies. <repositories> … <repository> <id>springsource-repo</id> <name>SpringSource Repository</name> <url>http://repo.springsource.org/release</url> </repository> </repositories> Now we need to add a few lines of XML into the src/main/webapp/WEB-INF/web.xml deployment descriptor file. At this point, we make the first step in connecting Spring with Vaadin. The location of the AppConfig class needs to match the full class name of the configuration class. <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.Annotation ConfigWebApplicationContext </param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.packtpub.vaadin.AppConfig </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> Create a new class AppConfig inside the com.packtpub.vaadin package and annotate it with the @Configuration annotation. Then create a new @Bean definition as shown: package com.packtpub.vaadin; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean(name="userService") public UserService helloWorld() { return new UserServiceImpl(); } } In order to have the recipe complete, we need to make a class that will represent a domain class. Create a new class called User. public class User { private String name; // generate getters and setters for name field } UserService is a simple interface defining a single method called getUser(). When the getUser() method is called in this recipe, we always create and return a new instance of the user (in the future, we could add parameters, for example login, and fetch user from the database). UserServiceImpl is the implementation of this interface. As mentioned, we could replace that implementation by something smarter than just returning a new instance of the same user every time the getUser() method is called. public interface UserService { public User getUser(); } public class UserServiceImpl implements UserService { @Override public User getUser() { User user = new User(); user.setName("Adela"); return user; } } Almost everything is ready now. We just make a new UI and get the application context from which we get the bean. Then, we call the service and obtain a user that we show in the browser. After we are done with the UI, we can run the application. public class AppUI extends UI { private ApplicationContext context; @Override protected void init(VaadinRequest request) { UserService service = getUserService(request); User user = service.getUser(); String name = user.getName(); Label lblUserName = new Label("Hi " + name + " !"); VerticalLayout layout = new VerticalLayout(); layout.setMargin(true); setContent(layout); layout.addComponent(lblUserName); } private UserService getUserService (VaadinRequest request) { WrappedSession session = request.getWrappedSession(); HttpSession httpSession = ((WrappedHttpSession) session).getHttpSession(); ServletContext servletContext = httpSession.getServletContext(); context = WebApplicationContextUtils.getRequired WebApplicationContext(servletContext); return (UserService) context.getBean("userService"); } } Run the following Maven commands in order to compile the widget set and run the application: mvn package mvn jetty:run How it works... In the first step, we have added dependencies to Spring. There was one additional dependency to cglib, Code Generation Library. This library is required by the @ Configuration annotation and it is used by Spring for making the proxy objects. More information about cglib can be found at http://cglib.sourceforge.net Then, we have added contextClass, contextConfigLocation and ContextLoaderListener into web.xml file. All these are needed in order to initialize the application context properly. Due to this, we are able to get the application context by calling the following code: WebApplicationContextUtils.getRequiredWebApplicationContext (servletContext); Then, we have made UserService that is actually not a real service in this case (we did so because it was not in the scope of this recipe). We will have a look at how to declare Spring services in the following recipes. In the last step, we got the application context by using the WebApplicationContextUtils class from Spring. WrappedSession session = request.getWrappedSession(); HttpSession httpSession = ((WrappedHttpSession) session).getHttpSession(); ServletContext servletContext = httpSession.getServletContext(); context = WebApplicationContextUtils.getRequired WebApplicationContext(servletContext); Then, we obtained an instance of UserService from the Spring application context. UserService service = (UserService) context.getBean("userService"); User user = service.getUser(); We can obtain a bean without knowing the bean name because it can be obtained by the bean type, like this context.getBean(UserService.class). There's more... Using the @Autowire annotation in classes that are not managed by Spring (classes that are not defined in AppConfig in our case) will not work, so no instances will be set via the @Autowire annotation. Handling login with Spring We will create a login functionality in this recipe. The user will be able to log in as admin or client. We will not use a database in this recipe. We will use a dummy service where we just hardcode two users. The first user will be "admin" and the second user will be "client". There will be also two authorities (or roles), ADMIN and CLIENT. We will use Java annotation-driven Spring configuration. Getting ready Create a new Maven project from the Vaadin archetype. mvn archetype:generate -DarchetypeGroupId=com.vaadin -DarchetypeArtifactId=vaadin-archetype-application -DarchetypeVersion=LATEST -Dpackaging=war -DgroupId=com.app -DartifactId=vaadin-spring-login -Dversion=1.0 Maven archetype generates the basic structure of the project. We will add the packages and classes, so the project will have the following directory and file structure: How to do it... Carry out the following steps, in order to create login with Spring framework: We need to add Maven dependencies in pom.xml to spring-core, spring-context, spring-web, spring-security-core, spring-security-config, and cglib (cglib is required by the @Configuration annotation from Spring). <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> Now we edit the web.xml file, so Spring knows we want to use the annotation-driven configuration approach. The path to the AppConfig class must match full class name (together with the package name). <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.Annotation ConfigWebApplicationContext </param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.app.config.AppConfig</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> We are referring to the AppConfig class in the previous step. Let's implement that class now. AppConfig needs to be annotated by the @Configuration annotation, so Spring can accept it as the context configuration class. We also add the @ComponentScan annotation, which makes sure that Spring will scan the specified packages for Spring components. The package names inside the @ComponentScan annotation need to match our packages that we want to include for scanning. When a component (a class that is annotated with the @Component annotation) is found and there is a @Autowire annotation inside, the auto wiring will happen automatically. package com.app.config; import com.app.auth.AuthManager; import com.app.service.UserService; import com.app.ui.LoginFormListener; import com.app.ui.LoginView; import com.app.ui.UserView; import org.springframework.context.annotation.Bean; import org.springframework.context. annotation.ComponentScan; import org.springframework.context. annotation.Configuration; import org.springframework.context. annotation.Scope; @Configuration @ComponentScan(basePackages = {"com.app.ui" , "com.app.auth", "com.app.service"}) public class AppConfig { @Bean public AuthManager authManager() { AuthManager res = new AuthManager(); return res; } @Bean public UserService userService() { UserService res = new UserService(); return res; } @Bean public LoginFormListener loginFormListener() { return new LoginFormListener(); } } We are defining three beans in AppConfig. We will implement them in this step. AuthManager will take care of the login process. package com.app.auth; import com.app.service.UserService; import org.springframework.beans.factory. annotation.Autowired; import org.springframework.security.authentication. AuthenticationManager; import org.springframework.security.authentication. BadCredentialsException; import org.springframework.security.authentication. UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core. AuthenticationException; import org.springframework.security.core. GrantedAuthority; import org.springframework.security.core. userdetails.UserDetails; import org.springframework.stereotype.Component; import java.util.Collection; @Component public class AuthManager implements AuthenticationManager { @Autowired private UserService userService; public Authentication authenticate (Authentication auth) throws AuthenticationException { String username = (String) auth.getPrincipal(); String password = (String) auth.getCredentials(); UserDetails user = userService.loadUserByUsername(username); if (user != null && user.getPassword(). equals(password)) { Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); return new UsernamePasswordAuthenticationToken (username, password, authorities); } throw new BadCredentialsException("Bad Credentials"); } } UserService will fetch a user based on the passed login. UserService will be used by AuthManager. package com.app.service; import org.springframework.security.core. GrantedAuthority; import org.springframework.security.core. authority.GrantedAuthorityImpl; import org.springframework.security.core. authority.SimpleGrantedAuthority; import org.springframework.security.core. userdetails.UserDetails; import org.springframework.security.core. userdetails.UserDetailsService; import org.springframework.security.core. userdetails.UsernameNotFoundException; import org.springframework.security.core. userdetails.User; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; public class UserService implements UserDetailsService { @Override public UserDetails loadUserByUsername (String username) throws UsernameNotFoundException { List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); // fetch user from e.g. DB if ("client".equals(username)) { authorities.add (new SimpleGrantedAuthority("CLIENT")); User user = new User(username, "pass", true, true, false, false, authorities); return user; } if ("admin".equals(username)) { authorities.add (new SimpleGrantedAuthority("ADMIN")); User user = new User(username, "pass", true, true, false, false, authorities); return user; } else { return null; } } } LoginFormListener is just a listener that will initiate the login process, so it will cooperate with AuthManager. package com.app.ui; import com.app.auth.AuthManager; import com.vaadin.navigator.Navigator; import com.vaadin.ui.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication. UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core. AuthenticationException; import org.springframework.security.core.context. SecurityContextHolder; import org.springframework.stereotype.Component; @Component public class LoginFormListener implements Button.ClickListener { @Autowired private AuthManager authManager; @Override public void buttonClick(Button.ClickEvent event) { try { Button source = event.getButton(); LoginForm parent = (LoginForm) source.getParent(); String username = parent.getTxtLogin().getValue(); String password = parent.getTxtPassword().getValue(); UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken (username, password); Authentication result = authManager.authenticate(request); SecurityContextHolder.getContext(). setAuthentication(result); AppUI current = (AppUI) UI.getCurrent(); Navigator navigator = current.getNavigator(); navigator.navigateTo("user"); } catch (AuthenticationException e) { Notification.show("Authentication failed: " + e.getMessage()); } } } The login form will be made as a separate Vaadin component. We will use the application context and that way we get bean from the application context by ourselves. So, we are not using auto wiring in LoginForm. package com.app.ui; import com.vaadin.ui.*; import org.springframework.context.ApplicationContext; public class LoginForm extends VerticalLayout { private TextField txtLogin = new TextField("Login: "); private PasswordField txtPassword = new PasswordField("Password: "); private Button btnLogin = new Button("Login"); public LoginForm() { addComponent(txtLogin); addComponent(txtPassword); addComponent(btnLogin); LoginFormListener loginFormListener = getLoginFormListener(); btnLogin.addClickListener(loginFormListener); } public LoginFormListener getLoginFormListener() { AppUI ui = (AppUI) UI.getCurrent(); ApplicationContext context = ui.getApplicationContext(); return context.getBean(LoginFormListener.class); } public TextField getTxtLogin() { return txtLogin; } public PasswordField getTxtPassword() { return txtPassword; } } We will use Navigator for navigating between different views in our Vaadin application. We make two views. The first is for login and the second is for showing the user detail when the user is logged into the application. Both classes will be in the com.app.ui package. LoginView will contain just the components that enable a user to log in (text fields and button). public class LoginView extends VerticalLayout implements View { public LoginView() { LoginForm loginForm = new LoginForm(); addComponent(loginForm); } @Override public void enter(ViewChangeListener.ViewChangeEvent event) { } }; UserView needs to identify whether the user is logged in or not. For this, we will use SecurityContextHolder that obtains the SecurityContext that holds the authentication data. If the user is logged in, then we display some data about him/her. If not, then we navigate him/her to the login form. public class UserView extends VerticalLayout implements View { public void enter(ViewChangeListener.ViewChangeEvent event) { removeAllComponents(); SecurityContext context = SecurityContextHolder.getContext(); Authentication authentication = context.getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { String name = authentication.getName(); Label labelLogin = new Label("Username: " + name); addComponent(labelLogin); Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); for (GrantedAuthority ga : authorities) { String authority = ga.getAuthority(); if ("ADMIN".equals(authority)) { Label lblAuthority = new Label("You are the administrator. "); addComponent(lblAuthority); } else { Label lblAuthority = new Label("Granted Authority: " + authority); addComponent(lblAuthority); } } Button logout = new Button("Logout"); LogoutListener logoutListener = new LogoutListener(); logout.addClickListener(logoutListener); addComponent(logout); } else { Navigator navigator = UI.getCurrent().getNavigator(); navigator.navigateTo("login"); } } } We have mentioned LogoutListener in the previous step. Here is how that class could look: public class LogoutListener implements Button.ClickListener { @Override public void buttonClick(Button.ClickEvent clickEvent) { SecurityContextHolder.clearContext(); UI.getCurrent().close(); Navigator navigator = UI.getCurrent().getNavigator(); navigator.navigateTo("login"); } } Everything is ready for the final AppUI class. In this class, we put in to practice all that we have created in the previous steps. We need to get the application context. That is done in the first lines of code in the init method. In order to obtain the application context, we need to get the session from the request, and from the session get the servlet context. Then, we use the Spring utility class, WebApplicationContextUtils, and we find the application context by using the previously obtained servlet context. After that, we set up the navigator. @PreserveOnRefresh public class AppUI extends UI { private ApplicationContext applicationContext; @Override protected void init(VaadinRequest request) { WrappedSession session = request.getWrappedSession(); HttpSession httpSession = ((WrappedHttpSession) session).getHttpSession(); ServletContext servletContext = httpSession.getServletContext(); applicationContext = WebApplicationContextUtils. getRequiredWebApplicationContext(servletContext); Navigator navigator = new Navigator(this, this); navigator.addView("login", LoginView.class); navigator.addView("user", UserView.class); navigator.navigateTo("login"); setNavigator(navigator); } public ApplicationContext getApplicationContext() { return applicationContext; } } Now we can run the application. The password for usernames client and admin is pass. mvn package mvn jetty:run How it works... There are two tricky parts from the development point of view while making the application: First is how to get the Spring application context in Vaadin. For this, we need to make sure that contextClass, contextConfigLocation, and ContextLoaderListener are defined in the web.xml file. Then we need to know how to get Spring application context from the VaadinRequest. We certainly need a reference to the application context in UI, so we define the applicationContext class field together with the public getter (because we need access to the application context from other classes, to get Spring beans). The second part, which is a bit tricky, is the AppConfig class. That class represents annotated Spring application configuration (which is referenced from the web.xml file). We needed to define what packages Spring should scan for components. For this, we have used the @ComponentScan annotation. The important thing to keep in mind is that the @Autowired annotation will work only for Spring managed beans that we have defined in AppConfig. When we try to add the @Autowired annotation to a simple Vaadin component, the autowired reference will remain empty because no auto wiring happens. It is up to us to decide what instances should be managed by Spring and where we use the Spring application context to retrieve the beans. Summary In this article, we saw how to add Spring into the Maven project. We also took a look at handling login with Spring Resources for Article:   Further resources on this subject: Vaadin Portlets in Liferay User Interface Development [Article] Creating a Basic Vaadin Project [Article] Getting Started with Ext GWT [Article]
Read more
  • 0
  • 0
  • 5010

article-image-creating-image-profile-cloning-existing-one
Packt
19 Jul 2013
5 min read
Save for later

Creating an Image Profile by cloning an existing one

Packt
19 Jul 2013
5 min read
(For more resources related to this topic, see here.) How to do it The following procedure will guide you through the steps required to clone a predefined ESXi Image Profile available from an ESXi Offline Bundle. It is a four step process: Verifying the existence of a Software Depot in the current session. Adding a Software Depot. Listing available Image Profiles. Cloning an Image Profile to form a new one. Verifying the existence of a Software Depot in the current session To verify whether there are any existing Software Depots defined in the current PowerCLI session, issue the following command: $DefaultSoftwareDepots Note that the command has not returned any values. Meaning, there are no Software Depots defined in the current session. If the needed Software Depot was already added then the command output will list the depot. In that case, you can skip step 2, Add a Software Depot, and start with step 3, List available Image Profiles. Adding a Software Depot Before you add a Software Depot, make sure that you have the Offline Bundle saved on to your local disk. The Offline Bundle can be downloaded from VMware's website or from the OEM's website. The bundle can either be an ESXi Image or a device driver bundle. We already have the Offline Bundle downloaded to the C:AutoDeploy-VIBS directory. Now, let's add this to the current PowerCLI session. To add the downloaded Software Depot, issue the following command: Add-EsxSoftwareDepot -DepotUrl C:AutoDeploy-VIBSESXi500-201111001.zip Once the Software Depot has been successfully added to the PowerCLI session, the command $DefaultSoftwareDepots should list the newly added Software Depot. You could also just issue the command Get-EsxSoftwareDepot to list all the added depots (Offline Bundles). Listing available Image Profiles Once the Software Depot has been added, the next step will be to list all the currently available Image Profiles from the depot by issuing the following command: Get-EsxImageProfile We see that there are two image profiles that the ESXi Offline Bundle offers. One is an ESXi Image, with no VMware Tools ISOs bundled with it, and the other is the standard image, with the VMware Tools ISOs bundled with it. Cloning an Image Profile to form a new one Now that we know there are two Image Profiles available, the next step will be to clone a needed Image Profile to form a new one. This is done by using the New-ESXImageProfile cmdlet. The cmdlet can be supplied with the name of the Image Profile as an argument. However, in most cases remembering the names of the Image Profiles available would be difficult. So the best way to work around this difficulty is to define an array variable to hold the names of the Image Profiles and then the array elements (Image Profile names) can be easily and individually addressed in the command. In this example, we will be using a user defined array variable $profiles to hold the output of the command Get-EsxImageProfile. The following expression will save the output of the Get-ESXImageProfile command to a variable $profiles. $profiles = Get-EsxImageProfile The $profiles variable now holds the two Image Profile names as array elements [0] and [1] sequentially. The following command can be issued to clone the array element [1] ESXi-5.1.10-799733-standard to form a new Image Profile, with a user defined name Profile001. New-EsxImageProfile -CloneProfile $profiles[1] -Name "Profile001" -Vendor VMware Once the command has been successfully executed, you can issue the Get-EsxImageProfile command to list the newly created Image Profile. How it works The PowerCLI session will have a list of Image Profiles available from the added Offline Bundle. During the process of creating a new Image profile, you verify whether a Software Depot is already added to the PowerCLI session using the $DefaultSoftwareDepots command. If there are no Software Depots added then the command will silently exit to the PowerCLI prompt. If there are Software Depots added then it would list the depots added showing the path to its XML file. This is referred to as a depot URL. The process of adding the Software Depot is pretty straightforward. First you need to make sure that you have downloaded the needed Offline Bundles to the server where you have PowerCLI installed. In this case it was downloaded and saved to the C:AutoDeploy-VIBs folder. Once the Offline Bundle is downloaded and saved to an accessible location, you can then issue the command Add-EsxSoftwareDepot to add the Offline Bundle as a depot to the PowerCLI session. Once the software has been added, you can then list all the Image Profiles available from the Offline Bundle. Then the chosen Image Profile is cloned to form a new Image Profile, which can then be customized by adding/removing VIBs. It can then be published as an Offline Bundle or an ISO. Summary We saw that all the predefined Image Profiles were available from an Offline Bundle that were read-only. To customize such Image Profiles, you needed to clone them to form new Image Profiles. We learned how to create a new Image Profile by cloning an existing one. Resources for Article : Further resources on this subject: Supporting hypervisors by OpenNebula [Article] Integration with System Center Operations Manager 2012 SP1 [Article] VMware View 5 Desktop Virtualization [Article]
Read more
  • 0
  • 0
  • 3343
Modal Close icon
Modal Close icon