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

How-To Tutorials

7019 Articles
article-image-securing-bpel-process
Packt
27 Oct 2010
9 min read
Save for later

Securing a BPEL process

Packt
27 Oct 2010
9 min read
WS-BPEL 2.0 for SOA Composite Applications with IBM WebSphere 7 Define, model, implement and monitor real-world BPEL 2.0 business processes with SOA-powered BPM Develop BPEL and SOA composite solutions with IBM's WebSphere SOA platform Automate business processes with WS-BPEL 2.0 and develop SOA composite applications efficiently A detailed explanation of advanced topics, such as security, transactions, human workflow, dynamic processes, fault handling, and more—enabling you to work smarter Core concepts BPEL as a specification does not provide any security concepts that we could leverage. All security aspects are left to the BPEL engine or, in other words, to the BPEL engine wrapper. In WebSphere, BPEL processes are implemented as SCA components. So for BPEL processes, we can leverage all security constructs that SCA architecture offers. A BPEL process can be secured on an SCA component level so that only authorized users can access it through the usage of a security permission qualifier. This qualifier defines that role-specific users must be assigned for accessing a specific SCA component, in our case a BPEL process. Before such a BPEL process is deployed on the server, it is possible to map specific users to the role qualifiers. At runtime, it is possible to dynamically add or remove users to and from this role. A very common standardized way to expose BPEL process to the outside world is through the use of web services. In WebSphere, every SCA component can be exposed as a web service through a web service export. There are four web service export types supported, depending on the communication protocol (HTTP(S) or JMS), message exchange format (SOAP v1.1 or v1.2), and Java implementation framework (JAX-WS or JAX-RPC). Web services use SOAP as a message exchange format. SOAP relies on XML. The root element of a SOAP message is a <soap:Envelope> that contains <soap:Header> and <soap:Body>. In the body, there are usually input data for the service operation (payload). Other data (such as credentials, correlation, and others) are contained in the header. Web services in Java can be implemented with JAX-WS (Java API for XML Web Services) or JAX-RPC (a predecessor of JAX-WS called Java API for XML-based Remote Procedure Call) API. JAX-WS uses annotations introduced in Java SE 5 to make development and deployment of web services and their clients an easier task. JAX-WS is the preferred approach to service development. In WebSphere, JAX-WS supports WS-Policy sets to configure web service behavior in a declarative way. WS-Policy is a framework for expressing characteristics (like capabilities or requirements) of web services. It uses flexible and extensible constructs. Each policy is a collection of many policy alternatives, each containing policy assertions. Policy assertions are used to express web service characteristics. In WebSphere, specific WS-Policy policies are grouped together in policy sets, each policy set containing one or more WS-Policy policies. The main purpose of using WS-Policy in WebSphere is to specify different web service behaviors, for example, to specify different security aspects. One of the most important security specifications for web services supported in WebSphere is WS-Security. WS-Security (WSS) is a specification for delivering end-to-end security for web services. It provides an extension to SOAP (to 1.1 and 1.2 versions) for assuring message content integrity and confidentiality. WS-Security supports a variety of security models such as PKI, Kerberos, and SSL. Moreover, WS-Security supports multiple security token formats (username token, binary security token, XML token, and EncryptedData token), trusted domains, signature formats and algorithms (Exclusive XML Canonicalization, SOAP Message Normalization), and encryption technologies (symmetric and asymmetric). A WSS username token contains a username and is extensible to include possible authentication data, such as a password and additional data to increase security like a nonce (a unique identifier to prevent replay attacks) or timestamp (to prevent replay attacks by leveraging message expiration methods). A WSS binary security token provides only one XML element which contains binary data (for example, X.509 certificate or Kerberos ticket). An XML token is an abstract token that is concretized into WSS subsequent specifications. One of the tokens is a SAML token (Security Assertion Markup Language), which is used for exchanging authentication and authorization data between different security domains (identity providers and service providers). An EncryptedData token is an encrypted version of any token contained in a WSS header to provide token confidentiality. Securing a BPEL process We will explain how to secure a BPEL process with an example. We will expose the BPEL process as a web service. This way, a client will be able to call it in a standardized way. Next, we will create a new WS-Policy set that will require the client to provide a WS-Security header with UsernameToken containing the username and password for user authentication. We will attach this WS-Policy set to our BPEL process's web service export to protect the process. Only authenticated users will have access to the BPEL process. We will then test the example, with and without providing credentials, to see if security is working. Next, we will see that authentication information (user's identity) is not automatically propagated to the BPEL process. So, the process does not know which user called it. We will extract a user's identity from UsernameToken and propagate this identity to the BPEL process. Through another round of testing, we will see that the user who called the process will become the process instance owner. The final step in this example will be to configure the BPEL process in a way that only authenticated users, who are authorized, will be able to call it. To achieve this, we will have to define the security permission qualifier on our BPEL process, define a role that will have access to our BPEL process, and map users to this role to actually allow specific users to access our BPEL process. Later on, we will be able to add or remove users from the role to enable runtime access permission update for specific users. Exposing a BPEL process as web service We will expose a BPEL process as a web service with the help of the following steps: Let us take the Travel Approval BPEL process and open it in the WebSphere Integration Developer. The Travel Approval process is an SCA component with an interface. The Travel Approval process and surrounding components are shown in the assembly diagram represented in the following screenshot: The Travel Approval process sends an e-mail to confirm the reservation. You can download the sample from http://www.packtpub.com. The sample can be deployed to the IBM WebSphere Process Server using the IBM WebSphere Integration Developer. We can expose this process as a web service by generating a web service export. We can generate the web service export by right-clicking on the TravelApproval process and selecting Generate Export... and then Web Service Binding from the context menu, as shown in the following screenshot: The Travel Approval process implements more than one interface, so a dialog asks us which interface to expose. We should select the interface that is used to run the process, that is, the TravelApprovalPT interface, as shown in the following screenshot: Next, we have to select the transport protocol. There are four options as we can see in the following image. The first two are using the HTTP protocol with JAX-WS as the implementation framework and the SOAP protocol of versions 1.1 and 1.2 respectively (the name Simple Object Access Protocol behind the SOAP abbreviation was dropped in version 1.2). SOAP 1.2 brings several advancements over SOAP 1.1. For example, it assures better interoperability, better support standards like XML Information Set (a set of definitions for use in other specifications), is truly protocol independent, and has better and more formalized extensibility. The third option uses JAX-RPC as the implementation framework for SOAP 1.1. The last option doesn't use HTTP as the transport protocol but instead uses JMS (Java Message Service).We will use WS-Policy to define authentication rules, so we need the WSPolicy support that is offered only with JAX-WS binding. We will choose usage of SOAP messages of version 1.2, that is, SOAP1.2/HTTP, as the latest standard, as shown in the following screenshot. Alternatively, we could also use SOAP 1.1 with JAX-WS. At this point, we need to save our assembly diagram, because we will rename the newly generated export to have a more descriptive name. We will use the refactoring option for renaming SCA components, imports, and exports. Refactoring is enabled by right-clicking on our newly created web service export, TravelApprovalPTExport1 | Refactor... | Rename, as shown in the following screenshot: We choose TravelApprovalWS as the new name for the export and click on Refactor: When we created the web service export, WebSphere Integration Developer generated the following artifacts: Web service binding TravelApprovalWS_TravelApprovalPTHttpBinding in namespace http://packtpub.com/bpel/travel/Binding A service called TravelApprovalWS_TravelApprovalPTHttpService with port TravelApprovalWS_TravelApprovalPTHttpPort and endpoint address http://localhost:9080/SecuringBPELWeb/sca/TravelApprovalWS Note that the endpoint address can change when the web service is deployed on another server. We can see all these details if we select our web service export in the assembly diagram and bring up its properties by clicking on Properties | Binding: All these details are actually defined in the WSDL file that was generated in our SecuringBPEL_lib library, which contains data types and interfaces. We can find the TravelApprovalWS_TravelApprovalPTHttpPort WSDL file under Web Service Ports in SecuringBPEL_lib, as shown in the following screenshot: When we open this WSDL file, we can see all the content we described earlier (binding, service, port, address). Notice that the <wsdl:import> element imports the actual (abstract) interface from TravelApprovalPT.wsdl: (Move the mouse over the image to enlarge.) In this section, we have created a web service export for our BPEL process and examined the details that occurred behind the scenes.
Read more
  • 0
  • 0
  • 2608

article-image-page-management-part-one-cms-design
Packt
14 Dec 2010
6 min read
Save for later

Page Management - Part One in CMS Design

Packt
14 Dec 2010
6 min read
  CMS Design Using PHP and jQuery Build and improve your in-house PHP CMS by enhancing it with jQuery Create a completely functional and a professional looking CMS Add a modular architecture to your CMS and create template-driven web designs Use jQuery plugins to enhance the "feel" of your CMS A step-by-step explanatory tutorial to get your hands dirty in building your own CMS         Read more about this book       (For more resources on this subject, see here.) How pages work in a CMS A "page" is simply the main content which should be shown when a certain URL is requested. In a non-CMS website, this is easy to see, as a single URL returns a distinct HTML file. In a CMS though, the page is generated dynamically, and may include features such as plugins, different views depending on whether the reader was searching for something, whether pagination is used, and other little complexities. In most websites, a page is easily identified as the large content area in the middle (this is an over-simplification). In others, it's harder to tell, as the onscreen page may be composed of content snippets from other parts of the site. We handle these differences by using page "types", each of which can be rendered differently on the frontend. Examples of types include gallery pages, forms, news contents, search results, and so on. In this article, we will create the simplest type, which we will call "normal". This consists of a content-entry textarea in the admin area, and direct output of that content on the front-end. You could call this "default" if you want, but since a CMS is not always used by people from a technical background, it makes sense to use a word that they are more likely to recognize. I have been asked before by clients what "default" means, but I've never been asked what "normal" means. At the very least, a CMS needs some way to create the simplest of web pages. This is why the "normal" type is not a plugin, but is built into the core. Listing pages in the admin area To begin, we will add Pages to the admin menu. Edit /ww.admin/header.php and add the following highlighted line: <ul> <li><a href="/ww.admin/pages.php">Pages</a></li> <li><a href="/ww.admin/users.php">Users</a></li> And one more thing—when we log into the administration part of the CMS, it makes sense to have the "front page" of the admin area be the Pages section. After all, most of the work in a CMS is done in the Pages section. So, we change /ww.admin/index.php so it is a synonym for /ww.admin/pages.php. Replace the /ww.admin/index.php file with this: <?php require 'pages.php'; Next, let's get started on the Pages section. First, we will create /ww.admin/pages.php: <?php require 'header.php'; echo '<h1>Pages</h1>'; // { load menu echo '<div class="left-menu">'; require 'pages/menu.php'; echo '</div>'; // } // { load main page echo '<div class="has-left-menu">'; require 'pages/forms.php'; echo '</div>'; // } echo '<style type="text/css"> @import "pages/css.css";</style>'; require 'footer.php'; Notice how I've commented blocks of code, using // { to open the comment at the beginning of the block, and // } at the end of the block. This is done because a number of text editors have a feature called "folding", which allows blocks enclosed within delimiters such as { and } to be hidden from view, with just the first line showing. For instance, the previous code example looks like this in my Vim editor: What the page.php does is to load the headers, load the menu and page form, and then load the footers. For now, create the directory /ww.admin/pages and create a file in it called /ww.admin/pages/forms.php: <h2>FORM GOES HERE</h2> And now we can create the page menu. Use the following code to create the file /ww.admin/pages/menu.php: <?php echo '<div id="pages-wrapper">'; $rs=dbAll('select id,type,name,parent from pages order by ord,name'); $pages=array(); foreach($rs as $r){ if(!isset($pages[$r['parent']]))$pages[$r['parent']]=array(); $pages[$r['parent']][]=$r; } function show_pages($id,$pages){ if(!isset($pages[$id]))return; echo '<ul>'; foreach($pages[$id] as $page){ echo '<li id="page_'.$page['id'].'">' .'<a href="pages.php?id='.$page['id'].'"'>' .'<ins>&nbsp;</ins>'.htmlspecialchars($page['name']) .'</a>'; show_pages($page['id'],$pages); echo '</li>'; } echo '</ul>'; } show_pages(0,$pages); echo '</div>'; That will build up a &ltul> tree of pages. Note the use of the "parent" field in there. Most websites follow a hierarchical "parent-child" method of arranging pages, with all pages being a child of either another page, or the "root" of the site. The parent field is filled with the ID of the page within which it is situated. There are two main ways to indicate which page is the "front" page (that is, what page is shown when someone loads up http://cms/ with no page name indicated). You can have one single page in the database which has a parent of 0, meaning that it has no parent—this page is what is looked for when http://cms/ is called. In this scheme, pages such as http://cms/pagename have their parent field set to the ID of the one page which has a parent of 0. You can have many pages which have 0 as their parent, and each of these is said to be a "top-level" page. One page in the database has a flag set in the special field which indicates that this is the front page. In this scheme, pages named like http://cms/pagename all have a parent of 0, and the page corresponding to http://cms/ can be located anywhere at all in the database. Case 1 has a disadvantage, in that if you want to change what page is the front page, you need to move the current page under another one (or delete it), then move all the current page's child-pages so they have the new front page's ID as a parent, and this can get messy if the new front-page already had some sub-pages—especially if there are any with equal names. Case 2 is a much better choice because you can change the front page whenever you want, and it doesn't cause any problems at all. When you view the site in your browser now, it looks like this:
Read more
  • 0
  • 0
  • 2608

article-image-alfresco-web-content-management-wcm-20-part-one
Packt
19 Mar 2010
9 min read
Save for later

Alfresco Web Content Management (WCM) 2.0 Part One

Packt
19 Mar 2010
9 min read
Web Content Management (WCM) Modern web site implementations are architected with two distinct sets of capabilities – creation and maintenance of the content and delivery of the content to the target audiences. Creation and maintenance of web content is called Web Content Management (WCM) and is a relatively new discipline in the history of web technology.   In the early days, web sites were simple with static content that changed infrequently. Modification of the content was not the biggest of challenges and such changes were typically performed by technical developers. Web technology and the associated disciplines have come a long way since those times. Today there are well-defined disciplines involved in creation of web presence such as information architecture, visual design, content strategy, and site development. Products of these disciplines are merged together and realized through enterprise application technology, which adds functionality and dynamic nature to web sites. Specialization of roles among these disciplines as well as the complexity of the modern technology has made content updates difficult and error prone when performed directly on stored content. A WCM system makes it easier to create and update content by hiding the technical details related to the storage and delivery of content. It becomes almost imperative to use a WCM system for sites that have highly dynamic content which may also need to be delivered on multiple channels such as web, handheld devices, and print media. In such situations, content can be created once and rendered automatically for different channels. The WCM products available today vary widely in terms of their capabilities, the underlying technologies and frameworks, and the extent to which they use open-source products as architecture components. Many WCM systems also offer presentation capabilities in order to facilitate delivery of content at least for the web medium. When discussing WCM features, it is useful to identify what WCM is and what it isn’t. WCM deals with creation, persistence, and maintenance of content. It may also include some support for presentation in terms of previewing the content being created or edited. However, fully-featured presentation frameworks or technologies, such as portals, should be evaluated separately, since majority of their concerns are significantly different. Products with integrated WCM and portal capabilities offer the convenience of a one-stop solution for building, managing, and delivering web content. On the other hand, products with only WCM capabilities, or at least clearly separable WCM capabilities, offer freedom to use rich and mature presentation technologies which may already be in place in the existing infrastructure. Let’s take a look at a few products, which represent various points along the spectrum between these two extremes. Microsoft SharePoint Server is a well-known product with a wide range of content management capabilities that go beyond WCM and portals. Similarly, EMC Documentum is a high-end platform for enterprise content management which can be used in almost any way enterprise content may be intended to be used. EMC Documentum provides products catering to specialized needs – Web Publisher for creating and managing web content, Site Caching Services for pushing content to Web or Application Servers, and integration options with portals for presenting content. Interwoven and Vignette also offer high-end WCM systems. There is also a wide range of open-source options for WCM which have developed large user bases. Joomla! (as well as Mambo, where Joomla!’s origins lie) offers an integrated WCM and portal technology built on the LAMP (Linux, Apache, MySQL, PHP) platform. Joomla! offers over 100 components for providing specific optional capabilities such as building user communities or incorporating shopping carts. Joomla! makes it very easy to set up a web site in minutes if you are willing to work with its content organization and presentation model. Alfresco is an open-source platform developed with the stated goal of bringing enterprise content management (ECM) capabilities to open source. The Alfresco leadership team brings content management experience from companies such as Documentum, Business Objects, and SeeBeyond. Alfresco has matured with two major releases over a period of 2.5 years. Alfresco enables Document Management, Collaboration, Records Management, Knowledge Management, Web Content Management and Imaging – some of the most common applications of enterprise content management. Alfresco WCM 2.0 was released recently and offers some exciting built-in features that promote development efficiency and reduce infrastructure demands. We will explore these aspects in this article.   WCM Challenges Every WCM system is expected to provide certain fundamental features. The core WCM feature is the ability to edit content through a user-friendly and technology-neutral (as much as possible) interface. The system also needs to provide security and the capability to allow a team to work on the content. WCM systems typically support versioning for content items. Finally, the content needs to be exported to a form suitable for web or application servers for delivering to the target audiences. There are certain other features that are not necessarily required in a WCM system, but are considered to be desirable and are supported by many contemporary WCM products. One such feature is the ability to store content in XML format. XML content facilitates publishing the same content through multiple channels such as web, wireless devices, and print media. Another common and desirable feature is the support for business processes or workflows. At the minimum a simple approval process is desired which can be used to review and approve the promotion of content changes to a live environment. The WCM features discussed so far focus on what a WCM system can do. However, some of the challenges for WCM initiatives deal with how a WCM system supports certain capabilities. Such aspects may significantly affect development efficiency, quality assurance, and infrastructure costs. We take a look at some of these concerns below. Simple static HTML pages seem to belong to a bygone era. Even simple web sites today are usually dynamic and frequently contain media (images, videos) and utilize code and a database. Today, web site management deals with managing content, media, and code together. As a result, the line separating a web application from a web site is a blur. Note that sometimes the term “content” is used to refer to all the resources managed by a CMS. For sites utilizing code and media along with plain content, it becomes important that all of these resources are managed in sync. For example, if a change is made to include a new user attribute in the user profile the corresponding code or configuration changes need to make it to the live environment, along with any presentation changes (web pages that will use this new attribute). These requirements become more complex when you consider the fact that different team members may be working on related artefacts and these changes need to go through the review process concurrently. Another aspect of managing dynamic web sites is that often multiple web pages need to change to reflect one feature change in the web site. For the example above, the new user attribute may require a change to the user registration screen, user profile screen, and possibly some site functionality that utilizes the given feature. Thus, adding an email format preference to the user profile may require changes to three pages, two code components, and one configuration file. These affected artefacts together form a change set – they all need to go into the web site together or none of them should. If one or more pieces in the change set were left out, the change would not function as expected and would likely introduce a bug. Change sets bear some similarity to transactions and versions. The description above reflects the similarity to a transaction since all the changes should either be committed or discarded together. On the other hand, suppose a change set implementing a particular feature was promoted to the live environment. It worked as designed and expected. However, it led to unexpected business impacts and now this change needs to be undone. The WCM system should make it easy to roll back the changes introduced by a change set. If the system kept track of web site snapshots – state of the complete site after each change set was promoted, it would be simpler to go back to a prior state of the web site. One of the trickier challenges of WCM systems is to provide multiple environments which are isolated but more or less similar in structure. For example, each developer requires an area where he/she can make changes without impacting other developers or to the live environment. However, each developer should only see his/her changes on top of the currently live content. Then multiple change sets might need to be reviewed by different reviewers concurrently. Each reviewer should only see the change set to be reviewed on top of the currently approved content. Thus, there is a need for an on-demand virtual copy of the web site which includes the approved content and a change set. Such an isolated environment is commonly referred to as a sandbox. In the rest of this article, we will explore the core features offered by Alfresco WCM 2.0 and how it addresses the WCM challenges described above.   Alfresco WCM 2.0 Alfresco is an open-source content management platform. Alfresco WCM 2.0 is an optional add-on which can be installed on top of the core platform to enable WCM capabilities. In this section, we will look at typical usage of Alfresco WCM 2.0 and highlight how it handles the challenges described earlier. Alfresco organizes storage in spaces. A space is a smart folder which can be associated with configurable rules. These rules control what happens to documents or other spaces that are added under the space. Among other things, these rules enable workflows within the platform, support automatic versioning, and automatic rendition generation.   Installing Alfresco WCM 2.0 adds two spaces to the repository – Web Projects and Web Forms, as shown below in the Alfresco standard web interface. The Web Projects space holds other spaces, where each space represents one web site. The Web Forms space holds templates for creating and publishing content for different content types such as a press release or a company profile.                           Two Spaces are Added by Alfresco WCM 2.0 Web content for a site is managed under a web project space which is created under Web Projects. For example, the following screenshot shows alfrescowww as a space created for managing content for this web site. A Space for Holding Content for a Web Site Continue reading Alfresco Web Content Management (WCM) 2.0 Part Two [ 1 | 2 ] Read Alfresco Web Content Management (WCM) 2.0 Part OneRead Alfresco Web Content Management (WCM) 2.0 Part Two
Read more
  • 0
  • 0
  • 2607

article-image-non-default-magento-themes
Packt
07 Oct 2009
4 min read
Save for later

Non-default Magento Themes

Packt
07 Oct 2009
4 min read
Uses of non-default themes Magento's flexibility in themes gives a lot of scope for possible uses of non-default themes. Along with the ability to have seasonal themes on our Magento store, non-default themes have a range of uses: A/B testing Easily rolled-back themes Changing the look and feel of specific pages, such as for a particular product within your store Creating brand-specific stores within your store, distinguishing your store's products further, if you sell a variety of the same products from different brands A/B testing A/B testing allows you to compare two different aspects of your store. You can test different designs on different weeks, and can then compare which design attracted more sales. Magento's support for non-default themes allows you to do this relatively easily. Bear in mind that the results of such a test may not represent what actually drives your customers to buy your store's products for a number of reasons. True A/B testing on websites is performed by presenting the different designs to your visitors at random. However, performing it this way may give you an insight in to what your customers prefer. Easily rolled-back themes If you want to make changes to your store's existing theme, then you can make use of a non-default theme to overwrite certain aspects of your store's look and feel, without editing your original theme. This means that if your customers don't like a change, or a change causes problems in a particular browser, then you can simply roll-back the changes, by changing your store's settings to display the original theme. Non-default themes A default theme is the default look and feel to your Magento store. That is, if no other styling or presentational logic is specified, then the default theme is the one that your store's visitors will see. Magento's default theme looks similar to the following screenshot: Non-default themes are very similar to the default themes in Magento. Like default themes, Magento's non-default themes can consist of one or more of the following elements: Skins—images and CSS Templates—the logic that inserts each block's content or feature (for example, the shopping cart) in to the page Layout—XML files that define where content is displayed Locale—translations of your store The major difference between a default and a non-default theme in Magento is that a default theme must have all of the layout and template files required for Magento to run. On the other hand, a non-default theme does not need all of these to function, as it relies on your store's default theme, to some extent. Locales in Magento: Many themes are already partially or fully translated into a huge variety of languages. Locales can be downloaded from the Magento Commerce website at http://www.magentocommerce.com/langs. Magento theme hierarchy In its current releases, Magento supports two themes: a default theme, and a non-default theme. The non-default theme takes priority when Magento is deciding what it needs to display. Any elements not found in the non-default theme are then found in the default theme specified. Future versions of Magento should allow more than one default theme to be used at a time, as well as allow more detailed control over the hierarchy of themes in your store. Magento theme directory structure Every theme in Magento must maintain the same directory structure for its files. The skin, templates, and layout are stored in their own directories. Templates Templates are located in the app/design/frontend/interface/theme/template directory of your Magento store's installation, where interface is your store's interface (or package) name (usually default), and theme is the name of your theme (for example, cheese). Templates are further organized in subdirectories by module. So, templates related to the catalog module are stored in app/design/frontend/interface/theme/template/catalog directory, whereas templates for the checkout module are stored in app/design/frontend/interface/theme/template/checkout directory. Layout Layout files are stored in app/design/frontend/interface/theme/layout. The name of each layout file refers to a particular module. For example, catalog.xml contains layout information for the catalog module, whereas checkout.xml contains layout information for the checkout module.
Read more
  • 0
  • 0
  • 2607

article-image-html5-canvas
Packt
11 Sep 2013
5 min read
Save for later

HTML5 Canvas

Packt
11 Sep 2013
5 min read
(For more resources related to this topic, see here.) Setting up your HTML5 canvas (Should know) This recipe will show you how to first of all set up your own HTML5 canvas. With the canvas set up, we can then move on to look at some of the basic elements the canvas has to offer and how we would go about implementing them. For this task we will be creating a series of primitives such as circles and rectangles. Modern video games make use of these types of primitives in many different forms. For example, both circles and rectangles are commonly used within collision-detection algorithms such as bounding circles or bounding boxes. How to do it... As previously mentioned we will begin by creating our own HTML5 canvas. We will start by creating a blank HTML file. To do this, you will need some form of text editor such as Microsoft Notepad (available for Windows) or the TextEdit application (available on Mac OS). Once you have a basic webpage set up, all that is left to do in order to create a canvas is to place the following between both body tags: <canvas id="canvas" width="800" height="600"></canvas> As previously mentioned, we will be implementing a number of basic elements within the canvas. In order to do this we must first link the JavaScript file to our webpage. This file will be responsible for the initialization, loading, and drawing of objects to the canvas. In order for our scripts to have any effect on our canvas we must create a separate file called canvas example. Create this new file within your text editor and then insert the following code declarations: var canvas = document.getElementById("canvas"), context = canvas.getContext("2d"); These declarations are responsible for retrieving both the canvas element and context. Using the canvas context, we can begin to draw primitives, text, and load textures into our canvas. We will begin by drawing a rectangle in the top-left corner of our canvas. In order to do this place the following code below our previous JavaScript declarations: context.fillStyle="#FF00FF";context.fillRect(15,15,150,75); If you were to now view the original webpage we created, you would see the rectangle being drawn in the top-left corner at position X: 15, Y: 15. Now that we have a rectangle, we can look at how we would go about drawing a circle onto our canvas. This can be achieved by means of the following code: context.beginPath();context.arc(350,150,40,0,2 * Math.PI);context.stroke(); How it works... The first code extract represents the basic framework required to produce a blank webpage and is necessary for a browser to read and display the webpage in question. With a basic webpage created, we then declare a new HTML5 canvas. This is done by assigning an id attribute, which we use to refer to the canvas within our scripts. The canvas declaration then takes a width and height attribute, both of which are also necessary to specify the size of the canvas, that is, the number of pixels wide and pixels high. Before any objects can be drawn to the canvas, we first need to get the canvas element. This is done through means of the getElementById method that you can see in our canvas example. When retrieving the canvas element, we are also required to specify the canvas context by calling a built-in HTML5 method known as getContext. This object gives access to many different properties and methods for drawing edges, circles, rectangles, external images, and so on. This can be seen when we draw a rectangle to our the canvas. This was done using the fillStyle property, which takes in a hexadecimal value and in return specifies the color of an element. Our next line makes use of the fillRect method, which requires a minimum of four values to be passed to it. These values include the X and Y position of the rectangle, as well as the width and height of the rectangle. As a result, a rectangle is drawn to the canvas with the color, position, width, and height specified. We then move on to drawing a circle to the canvas, which is done by firstly calling a built-in HTML canvas method known as BeginPath. This method is used to either begin a new path or to reset a current path. With a new path setup, we then take advantage of a method known as Arc that allows for the creation of arcs or curves, which can be used to create circles. This method requires that we pass both an X and Y position, a radius, and a starting angle measured in radians. This angle is between 0 and 2 * Pi where 0 and 2 are located at the 3 o'clock position of the arc's circle. We also must pass an ending angle, which is also measured in radians. The following figure is taken directly from the W3C HTML canvas reference, which you can find at the following link http://bit.ly/UCVPY1: Summary In this article we saw how to first of all set up our own HTML5 canvas. With the canvas set up, we can then move on to look at some of the basic elements the canvas has to offer and how we would go about implementing them. Resources for Article: Further resources on this subject: Building HTML5 Pages from Scratch [Article] HTML5 Presentations - creating our initial presentation [Article] HTML5: Generic Containers [Article]
Read more
  • 0
  • 0
  • 2606

article-image-safely-manage-different-versions-content-plone
Packt
08 Oct 2009
2 min read
Save for later

Safely Manage Different Versions of Content with Plone

Packt
08 Oct 2009
2 min read
(For more resources on Plone, see here.) Introducing versioning Now that you have learned how to add various types of content, from pages to events to news items, we're ready to introduce a feature of Plone called versioning, which is an important part of content management. The content items you work with in your Plone site may go through many changes over time. Plone provides versioning information to help you manage your content from the time it was initially created through to the current version. By default, Plone provides versioning for the following content types: Pages News Items Events Links Other content types can be configured to provide versioning through the Plone Control Panel under Types. Although you may enable the File type to use versioning, the only changes that are tracked are those items actually describing the File (for example, Title, Description, and so on). The changes to the contents of the File are not tracked. Creating a new version Versions are created each time you save your content. Note that there is a Change note field at the bottom of the Edit page for content items with versioning enabled: The information entered in the Change note field will be stored along with other versioning information, which you are able to view through the History tab. Viewing the version history You can view the list of all of the versions of a content item by clicking on the History tab for that content item. In the History view that you can see in the following screenshot, the most recent version is listed fi rst. Clicking on any of the column headers will re-sort the listing based on that column heading. The most current version is always labeled Working Copy in the History view. Previewing previous versions To preview a specific version, simply click the preview link of the desired revision. In the following example, revision 3 has been identified, and will be displayed if this link is clicked: On the subsequent page, you may either click on the jump down link to the point of the content preview: or you may scroll down the page in order to see the actual preview:
Read more
  • 0
  • 0
  • 2602
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-appium-essentials
Packt
09 Apr 2015
9 min read
Save for later

Appium Essentials

Packt
09 Apr 2015
9 min read
In this article by Manoj Hans, author of the book Appium Essentials, we will see how toautomate mobile apps on real devices. Appium provides the support for automating apps on real devices. We can test the apps in a physical device and experience the look and feel that an end user would. (For more resources related to this topic, see here.) Important initial points Before starting with Appium, make sure that you have all the necessary software installed. Let's take a look at the prerequisites for Android and iOS: Prerequisites for Android Prerequisites for iOS Java (Version 7 or later) Mac OS (Version 10.7 or later) The Android SDK API, Version 17 or higher Xcode (Version 4.6.3 or higher; 5.1 is recommended) A real Android device An iOS provisional profile Chrome browser on a real device An iOS real device Eclipse The SafariLauncher app TestNG ios-webkit-debug-proxy The Appium Server Java Version 7 The Appium client library (Java) Eclipse Selenium Server and WebDriver Java library TestNG The Apk Info app The Appium server   The Appium client library (Java)   Selenium Server and WebDriver Java library While working with the Android real device, we need to enable USB debugging under Developer options. To enable USB debugging, we have to perform the following steps: Navigate to Settings | About Phone and tap on Build number seven times (assuming that you have Android Version 4.2 or newer); then, return to the previous screen and find Developer options, as shown in the following screenshot: Tap on Developer options and then tap on the ON switch to switch on the developer settings (You will get an alert to allow developer settings; just click on the OK button.). Make sure that the USB debugging option is checked, as shown here: After performing the preceding steps, you have to use a USB cable to connect your Android device with the desktop. Make sure you have installed the appropriate USB driver for your device before doing this. After connecting, you will get an alert on your device asking you to allow USB debugging; just tap on OK. To ensure that we are ready to automate apps on the device, perform the following steps: Open Command Prompt or terminal (on Mac). Type adb devices and press the Enter button. You will get a list of Android devices; if not, then try to kill and start the adb server with the adb kill-server and adb start-server commands. Now, we've come to the coding part. First, we need to set the desired capabilities and initiate an Android/iOS driver to work with Appium on a real device. Let's discuss them one by one. Desired capabilities for Android and initiating the Android driver We have two ways to set the desired capabilities, one with the Appium GUI and the other by initiating the desired capabilities object. Using the desired capabilities object is preferable; otherwise, we have to change the desired capabilities in the GUI repeatedly whenever we are testing another mobile app. Let's take a look at the Appium GUI settings for native and hybrid apps: Perform the following steps to set the Android Settings: Click on the Android Settings icon. Select Application Path and provide the path of the app. Click on Package and choose the appropriate package from the drop-down menu. Click on Launch Activity and choose an activity from the drop-down menu. If the application is already installed on the real device, then we don't need to follow steps 2-4. In this case, we have to install the Apk Info app on the device to know the package and activities of the app and set them using the desired capabilities object, which we will see in the next section. You can easily get the 'Apk info' app from the Android Play Store. Select PlatformVersion from the dropdown. Select Device Name and type in a device name (For example, Moto X). Now, start the Appium Server. Perform the following steps to set the Android Settings for web apps: Click on the Android Settings icon. Select PlatformVersion from the dropdown. Select Use Browser and choose Chrome from the dropdown. Select Device Name and type in a device name (For example, Moto X). Now, start the Appium Server. Let's discuss how to initiate the desired capabilities object and set the capabilities. Desired capabilities for native and hybrid apps Here we will directly dive into the code with comments. First, we need to import the following packages: import java.io.File;import org.openqa.selenium.remote.DesiredCapabilities;import io.appium.java_client.remote.MobileCapabilityType; Now, let's set the desired capabilities for the native and hybrid apps: DesiredCapabilities caps = new DesiredCapabilities();//To create an objectFile app=new File("path of the apk");//To create file object to specify the app pathcaps.setCapability(MobileCapabilityType.APP,app);//If app is already installed on the device then no need to set this capability.caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");//To set the Android versioncaps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");//To set the OS namecaps.setCapability(MobileCapabilityType.DEVICE_NAME,"Moto X");//You can change the device name as yours.caps.setCapability(MobileCapabilityType.APP_PACKAGE, "package name of your app (you can get it from apk info app)"); //To specify the android app packagecaps.setCapability(MobileCapabilityType.APP_ACTIVITY, "Launch activity of your app (you can get it from apk info app)");//To specify the activity which we want to launch Desired capabilities for web apps In Android mobile web apps, some of the capabilities that we used in native and hybrid apps such as APP, APP PACKAGE, and APP ACTIVITY are not needed because we launch a browser here. First, we need to import the following packages: import java.io.File;import org.openqa.selenium.remote.DesiredCapabilities;import io.appium.java_client.remote.MobileCapabilityType; Now, let's set the desired capabilities for the web apps: DesiredCapabilities caps = new DesiredCapabilities();//To create an objectcaps.setCapability(MobileCapabilityType.PLATFORM_VERSION, "4.4");//To set the android versioncaps.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");//To set the OS namecaps.setCapability(MobileCapabilityType.DEVICE_NAME,"Moto X");//You can change the device name as yourscaps.setCapability(MobileCapabilityType.BROWSER_NAME,"Chrome"); //To launch the Chrome browser We are done with the desired capability part; now, we have to initiate the Android driver to connect with the Appium Server by importing the following packages: import io.appium.java_client.android.AndroidDriver;import java.net.URL; Then, initiate the Android driver as shown here: AndroidDriver driver = new AndroidDriver (new URL("http://127.0.0.1:4723/wd/hub"), caps);//TO pass the url where Appium server is running This will launch the app in the Android real device using the configurations specified in the desired capabilities. Installing provisional profile, SafariLauncher, and ios-webkit-debug-proxy Before moving on to the desired capabilities for iOS, we have to make sure that we have set up a provisional profile and installed the SafariLauncher app and ios-webkit-debug-proxy to work with the real device. First, let's discuss the provisional profile. Provisional profile This profile is used to deploy an app on a real iOS device. To do this, we need to join the iOS Developer Program (https://developer.apple.com/programs/ios/). For this, you will have to pay USD 99. Now, visit https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html#//apple_ref/doc/uid/TP40012582-CH30-SW24 to generate the profile. After this, you will also need to install provisional profile on your real device; to do this, perform the following steps: Download the generated provisional profile. Connect the iOS device to a Mac using a USB cable. Open Xcode (version 6) and click on Devices under the Window menu, as shown here: Now, context click on the connected device and click on Show Provisional Profiles...: Click on +, select the downloaded profile, and then click on the Done button, as shown in the following screenshot: SafariLauncher app and ios-webkit-debug-proxy The SafariLauncher app is used to launch the Safari browser on a real device for web app testing. You will need to build and deploy the SafariLauncher app on a real iOS device to work with the Safari browser. To do this, you need to perform the following steps: Download the source code from https://github.com/snevesbarros/SafariLauncher/archive/master.zip. Open Xcode and then open the SafariLauncher project. Select the device to deploy the app on and click on the build button. After this, we need to change the SafariLauncher app in Appium.dmg; to do this, perform the following steps: Right-click on Appium.dmg. Click on Show Package Contents and navigate to Contents/Resources/node_modules/appium/build/SafariLauncher. Now, extract SafariLauncher.zip. Navigate to submodules/SafariLauncher/build/Release-iphoneos and replace the SafariLauncher app with your app. Zip submodules and rename it as SafariLauncher.zip. Now, we need to install the ios-webkit-debug-proxy on Mac to establish a connection in order to access the web view. To install the proxy, you can use brew and run the command brew install ios-webkit-debug-proxy in the terminal (this will install the latest tagged version), or you can clone it from Git and install it using the following steps: Open the terminal, type git clone https://github.com/google/ios-webkit-debug-proxy.git, and then click on the Enter button. Then, enter the following commands: cd ios-webkit-debug-proxy ./autogen.sh ./configure make sudo make install We are now all set to test web and hybrid apps. Summary In this article, we looked at how we can execute the test scripts of native, hybrid, and web mobile apps on iOS and Android real devices. Specifically, we learned how to perform actions on native mobile apps and also got to know about the desired capabilities for real devices. We ran a test with the Android Chrome browser and learned how to load the Chrome browser on an Android real device with the necessary capabilities. We then moved on to starting the Safari browser on a real device and setting up the desired capabilities to test web applications. Lastly, we looked at how easily we can automate hybrid apps and switch from native to web view. Resources for Article: Further resources on this subject: Cross-browser Tests using Selenium WebDriver [article] First Steps with Selenium RC [article] Selenium Testing Tools [article]
Read more
  • 0
  • 0
  • 2602

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

Class-less Objects in JavaScript

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

article-image-installing-alfresco-software-development-kit-sdk
Packt
28 Oct 2009
6 min read
Save for later

Installing Alfresco Software Development Kit (SDK)

Packt
28 Oct 2009
6 min read
Obtaining the SDK If you are running the Enterprise network, it is likely that the SDK has been provided to you as a binary. Alternatively, you can check out the Enterprise source code and build it yourself. In the Enterprise SVN repository, specific releases are tagged. So if you wanted 2.2.0, for example, you'd check out V2.2.0-ENTERPRISE-FINAL. The Enterprise SVN repository for the Enterprise network is password-protected. Consult your Alfresco representative for the URL, port, and credentials that are needed to obtain the Enterprise source code. Labs network users can either download the SDK as a binary from SourceForge (https://sourceforge.net/project/showfiles.php?group_id=143373&package_id=189441) or check out the Labs source code and build it. The SVN URL for the Labs source code is svn://svn.alfresco.com. In the Labs repository, nothing is tagged. You must check out HEAD. Step-by-Step: Building Alfresco from Source Regardless of whether you are using Enterprise or Labs, if you've decided to build from the source it is very easy to do it. At a high level, you simply check out the source and then run Ant. If you've opted to use the pre-compiled binaries, skip to the next section. Otherwise, let's use Ant to create the same ZIP/TAR file that is available on the download page. To do that, follow these steps: Check out the source from the appropriate SVN repository, as mentioned earlier. Set the TOMCAT_HOME environment variable to the root of your Apache Tomcat install directory. Navigate to the root of the source directory, then run the default Ant target: ant build.xml ant build.xml It will take a few minutes to build everything. When it is done, run the distribute task like this: ant -f continuous.xml distribute Again, it may take several minutes for this to run. When it is done, you should see several archives in the build|dist directory. For example, running this Ant task for Alfresco 3.0 Labs produces several archives. The subset relevant to the article includes: alfresco-labs-sdk-*.tar.gz alfresco-labs-sdk-*.zip alfresco-labs-tomcat-*.tar.gz alfresco-labs-tomcat-*.zip alfresco-labs-war-*.tar.gz alfresco-labs-war-*.zip alfresco-labs-wcm-*.tar.gz alfresco-labs-wcm-*.zip You should extract the SDK archive somewhere handy. The next step will be to import the SDK into Eclipse. Setting up the SDK in Eclipse Nothing about Alfresco requires you to use Eclipse or any other IDE. But Eclipse is very widely used and the Alfresco SDK distribution includes Eclipse projects that can easily be imported into Eclipse, so that's what these instructions will cover. In addition to the Alfresco JARs, dependent JARs, Javadocs, and source code, the SDK bundle has several Eclipse projects. Most of the Eclipse projects are sample projects showing how to write code for a particular area of Alfresco. Two are special, however. The SDK AlfrescoEmbedded project and the SDK AlfrescoRemote project reference all of the JARs needed for the Java API and the Web Services API respectively. The easiest way to make sure your own Eclipse project has everything it needs to compile is to import the projects bundled with the SDK into your Eclipse workspace, and then add the appropriate SDK projects to your project's build path. Step-by-Step: Importing the SDK into Eclipse Every developer has his or her own favorite way of configuring tools. If you are going to work with multiple versions of Alfresco, you should use version-specific Eclipse workspaces. For example, you might want to have a workspace-alfresco-2.2 workspace as well as a workspace-alfresco-3.0 workspace, each with the corresponding Alfresco SDK projects imported. Then, if you need to test customizations against a different version of the Alfresco SDK, all you have to do is switch your workspace, import your customization project if it isn't in the workspace already, and build it. Let's go ahead and set this up. Follow these steps: In Eclipse, select File|Switch Workspace or specify a new workspace location. This will be your workspace for a specific version of the Alfresco SDK so use a name such as workspace-alfresco-3.0. Eclipse will restart with an empty workspace. Make sure the Java compiler compliance level preference is set to 5.0 (Window|Preferences|Java|Compiler). If you forget to do that, Eclipse won't be able to build the projects after they are imported. Select File|Import|Existing Projects into Workspace. For the root directory, specify the directory where the SDK was uncompressed. For the root directory, specify the directory where the SDK was uncompressed. You want the root SDK directory, not the Samples directory. Select all of the projects that are listed and click Import. After the import, Eclipse should be able to build all projects cleanly. If not, double-check the compiler compliance level. If that is set but there are still errors, make sure you imported all SDK projects including SDK AlfrescoEmbedded and SDK AlfrescoRemote. Now that the files are in the workspace, take a look at the Embedded project. That's quite a list of dependent JAR files! The Alfresco-specific JARs all start with alfresco-. It depends on what you are doing, of course, but the JAR that is referenced most often is likely to be alfresco-repository.jar because that's where the bulk of the API resides. The SDK comes with zipped source code and Javadocs, which are both useful references (although the Javadocs are pretty sparse). It's a good idea to tell Eclipse where those files are, so you can drill in to the Alfresco source when debugging. To do that, right-click on the Alfresco JAR, and then select Properties. You'll see panels for Java Source Attachment and Javadoc Location that you can use to associate the JAR with the appropriate source and Javadoc archives. The following image shows the Java Source Attachment for alfresco-repository.jar: The following image shows the Javadoc Location panel for alfresco-repository.jar. Source and Javadoc are provided for each of the Alfresco JARs, as shown in the following table. Note that source and Javadoc for everything is available. This is open source software after all, not just all bundled with the SDK: Alfresco JAR Source archive Javadoc archive alfresco-core.jar Src|core-src.zip Doc|api|core-doc.zip alfresco-remote-api.jar Src|remote-api-src.zip Doc|api|remote-api-doc.zip alfresco-web-client.jar src|web-client-src.zip doc|api|web-client-doc.zip alfresco-repository.jar src|repository-src.zip doc|api|repository-doc.zip    
Read more
  • 0
  • 0
  • 2601

article-image-processing-and-managing-participants-civicrm
Packt
31 Mar 2011
9 min read
Save for later

Processing and Managing Participants in CiviCRM

Packt
31 Mar 2011
9 min read
Using CiviCRM Develop and implement a fully functional, systematic CRM plan for your organization Using CiviCRM Processing and managing participants You've configured your event, tested it, and publicly promoted the online information page and registration form. Before you know it, event registrations start rolling in. Now what? As with so many other areas of CiviCRM, these records may be viewed collectively through search tools or on an individual-contact basis. In this section, we'll walk through the event registration as it is viewed through the contact's record and then briefly review importing participant records. Working with event registrations A contact's history of event attendance will appear in their Events tab. From this tab, you can view, edit, or delete an existing registration, or create a new registration for the contact. Notice that there are two buttons above the event history listing, namely, Add Event Registration and Submit Credit Card Event Registration. The first is used for registrations that do not involve real time credit card processing through the system. This may include free events, payments by check, cash, EFT, or a credit card that was processed outside of the system. The second button should be used if you will be processing a credit card directly through CiviCRM. If you have not configured a payment processor, or your payment processor does not handle integrated payments (for example, PayPal Standard or Google Checkout, which redirect you to an external site to process the payment), then that button will not be visible. The new registration form allows you to select the event you wish to register the individual for, the fees and fields specific to the event, payment options, and receipting options. The following screenshot shows the top half of the form: There are several things to note about this form: The event drop-down list will only show current and future events. If you wish to register someone for an event in the past, you must click the Include past event(s) in this select list link, which will reload the form with the full list of events. This is done to reduce any confusion and simplify the event selection process. If you have created any custom data fields attached to participants, they will appear and be available only when the selections match their "used for" criteria. For example, if you have created custom fields for the participant role Guest, they will only appear when you change the role on this form. If you have custom fields attached to the event type Conference, they will only appear if the event selected is associated with that event type. If you are expecting, but not seeing a certain custom field, make sure your selections match how that field is configured to be used. Directly below the event fee block is an option to record a payment with this registration. Checking the box reveals a series of contribution-related fields, as shown in the following screenshot: It is important to understand that an event registration in which fees are collected involves both an event participant record and an associated contribution record. While you could process these separately, we strongly advise that you manage them through this single interface. In addition to being easier than entering them separately (since you may handle both records at once), doing so creates a link between the two records. If you return at a later date to view this event registration, you will see the related contribution record summarized below it. Likewise, if you enter the associated contribution record, you will see the event record summarized below it. Revenue totals for the event in reports will also reflect the linked records. Entering them separately will not build that connection. Handling expected payments Inevitably, you will receive event registrations by mail, fax, or phone, in which payment has not been submitted with the event registration. Though you have not actually received the payment, there is an expected payment and consequently, the best practice is to enter the payment as a pending contribution. Use the Record Payment option to log the contribution, but do not complete the Paid By field, and change the Payment Status field to Pending. Why is this recommended? For two reasons: first, it captures the reality of the data better. You have received a registration that implies a commitment to pay. This is different from a registration for a guest, speaker, or other VIP attendee for whom you do not plan to charge a fee. Secondly, it provides better tools for tracking payments due. If each registrant in the above scenario has a pending contribution payment, you can easily run a search to find out the total due and process invoices or follow- up communication accordingly. In essence, it gives you a better overview of your actual financial position, and a clear data path to those who owe you payment. Registrations received through your public-facing event registration page will also have both an event and contribution record created. Pay later registrations will have contribution records with a status of Pending, indicating that a payment has not yet been received. When you receive payment, first record the details in the contribution record and change the status to Completed. Doing so will automatically change the status of the associated event registration record to reflect that the payment has been received. Note that the reverse action does not have the same effect: changing the status of a registration to completed does not likewise change the status of its associated contribution record. This supports situations where you want to allow people to attend the event (marked completed) even though they will pay after the event (marked pending). Before leaving the event record displayed within the contact record, we want to point out one additional feature. From the event tab, click on View to see the registration details. From this screen, you'll notice a button to create a name badge. Clicking on this option will direct you to a form where you select the template to be used and trigger the creation of a PDF file with the name badge. In the following Tracking, searching, and reporting section, we will review how to create name badges for all event participants in bulk. For now, it's useful to see how an individual name badge can be created. Importing participant records As with other areas of CiviCRM, the event functions include a tool for importing event registrations. This is particularly useful when you are initially migrating data from an external database such as MS Access or MS SQL Server. It may come in handy at times depending on your organization structure and how CiviCRM is being used. Let's say your organization consists of five chapters geographically oriented to cover the entire state. Each chapter hosts local events and handles all onsite management through volunteers. The registration process is centralized through the state-wide organization using CiviCRM, so the contact participant list is generated and e-mailed to the chapter coordinator the day before the event. Suppose some of these events allow walk-in registrations and others include continuing education credits that must have verified attendance in order to be earned. In other words, the organization must not only track if people have registered, but must also track whether they actually attended. You choose to handle this by sending a .csv (comma-separated) export file the evening before the event to the chapter coordinator. The coordinator welcomes people as they arrive at the event and uses spreadsheet software to mark each person who attends in the .csv file. They add new rows for walk-ins. That file is sent back to the main office at the conclusion of the event and is imported into CiviCRM in two steps: existing registrants are imported using the Update option, where the participant status value reflects who attended; and the new registrants are imported using the Insert option, and then are matched with existing records using their name and e-mail. The import tool is very similar to what we saw in other areas. The four-step wizard consists of loading a file and configuring the import settings, mapping the file's fields to CiviCRM fields, previewing the results, and completing the import. An error file will be generated and will be available for download if any problems are discovered with any records. To access the import tool, visit Events | Import Participants. There are a few things to note that are specific to importing events: Participant import only accepts .csv files. You cannot connect to a MySQL database as with the contact import. The most significant difference between importing participants and importing contacts is the behavior of the Update option for handling duplicates. The Update option requires the presence of an existing participant record, which must be identified using the unique participant ID value. Consequently, you will only use it in scenarios similar to the one we just discussed, where the participant list is exported from the system, changes are made, and it is then imported back into the system. If the Update option is used, CiviCRM will not process new registration records. In this way, it differs from the contact import that matches and updates existing records and creates new records for those that do not match. As one might expect, the field mapping options available for the participant import include a number of registration-related fields. Take note of those in red, as they are required in order to successfully import these records. They include the Event ID and Participant Status. The former can be obtained from the Manage Events page. Several of the fields highlighted in red are used for matching to the contact record. Not all of these are required; only ones sufficient for making a valid match are required. For example, you do not need the internal contact ID and the first/last name. Either of these is sufficient for making a match.
Read more
  • 0
  • 0
  • 2597
article-image-working-report-builder-microsoft-sql-server-2008-part-2
Packt
22 Oct 2009
3 min read
Save for later

Working with the Report Builder in Microsoft SQL Server 2008: Part 2

Packt
22 Oct 2009
3 min read
Enabling and reviewing My Reports As described in Part 1 the My Reports folder needs to be enabled in order to use the folder or display it in the Open Report dialogue. The RC0 version had a documentation bug which has been rectified (https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=366413) Getting ready In order to enable the My Reports folder you need to carry out a few tasks. This will require authentication and working with the SQL Server Management Studio. These tasks are listed here: Make sure the Report Server has started. Make sure you have adequate permissions to access the Servers. Open the Microsoft SQL Server Management Studio as described previously. Connect to the Reporting Services after making sure you have started the Reporting Services. Right-click the Report Server node. General Execution History Logging Security Advanced The Server Properties window is displayed with a navigation list on the left consisting of the following: In the General page the name, version, edition, authentication mode, and URL of Reporting Service is displayed. Download of an ActiveX Client Print control is enabled by default. In order to work with Report Builder effectively and provide a My Reports folder for each user, you need to place a check mark for the check box Enable a My Reports folder for each user. The My Reports feature has been turned on as shown in the next screenshot. In the Execution page there is choice for report timeout execution, with the default set such that the report execution expires after 1800 seconds. In the History page there is choice between keeping an unlimited number of snapshots in the report history (default) or to limit the copies allowing you to specify how many to be kept. In the Logging page, report execution logging is enabled and the log entries older than 60 days are removed by default. This can be changed if desired. In the Security page, both Windows integrated security for report data sources and ad hoc report executions are enabled by default. The Advanced page shows several more items including the ones described thus far as shown in the next figure. In the General page enable the My Reports feature by placing a check mark. Click on the Advanced list item in the left. The Advanced page is displayed as shown: Now expand the Security node of Reporting Services and you will see that the My Reports role is present in the list of roles as shown. This is also added to the ReportServer database. The description of everything that a user with the assignment My Reports role can do is as follows: May publish reports and linked reports, manage folders, reports, and resources in a users My Reports folder. Now bring up Report Builder 2.0 by clicking Start | All Programs | Microsoft SQL Server 2008 Report Builder | Report Builder 2.0. Report Builder 2.0 is displayed. Click on Office Button | Open. The Open Report dialogue appears as shown. When the report Server is offline, the default location is My Documents, like Microsoft products Excel and MS Access. Choose the Recent sites and Servers. The Report server that is active should get displayed here as shown: Highlight the Server URL and click Open. All the folders and files on the server become accessible as shown: Open the Report Manager by providing its URL address. Verify that a My Reports folder is created for the user (current user). There could be slight differences in the look of the interface depending on whether you are using the RTM or the final version of SQL Server 2008 Enterprise edition.
Read more
  • 0
  • 0
  • 2596

article-image-customize-backend-component-joomla-15
Packt
04 Jun 2010
13 min read
Save for later

Customize backend Component in Joomla! 1.5

Packt
04 Jun 2010
13 min read
(Read more interesting articles on Joomla! 1.5here.) Itemized data Most components handle and display itemized data. Itemized data is data having many instances; most commonly this reflects rows in a database table. When dealing with itemized data there are three areas of functionality that users generally expect: Pagination Ordering Filtering and searching In this section we will discuss each of these areas of functionality and how to implement them in the backend of a component. Pagination To make large amounts of itemized data easier to understand, we can split the data across multiple pages. Joomla! provides us with the JPagination class to help us handle pagination in our extensions. There are four important attributes associated with the JPagination class: limitstart: This is the item with which we begin a page, for example the first page will always begin with item 0. limit: This is the maximum number of items to display on a page. total: This is the total number of items across all the pages. _viewall: This is the option to ignore pagination and display all items. Before we dive into piles of code, let's take the time to examine the listFooter, the footer that is used at the bottom of pagination lists: The box to the far left describes the maximum number of items to display per page (limit). The remaining buttons are used to navigate between pages. The final text defines the current page out of the total number of pages. The great thing about this footer is we don't have to work very hard to create it! We can use a JPagination object to build it. This not only means that it is easy to implement, but that the pagination footers are consistent throughout Joomla!. JPagination is used extensively by components in the backend when displaying lists of items. In order to add pagination to our revues list we must make some modifications to our backend revues model. Our current model consists of one private property $_revues and two methods: getRevues() and delete(). We need to add two additional private properties for pagination purposes. Let's place them immediately following the existing $_revues property: /** @var array of revue objects */var $_revues = null;/** @var int total number of revues */var $_total = null;/** @var JPagination object */var $_pagination = null; Next we must add a class constructor, as we will need to retrieve and initialize the global pagination variables $limit and $limitstart. JModel objects store a state object in order to record the state of the model. It is common to use the state variables limit and limitstart to record the number of items per page and starting item for the page. We set the state variables in the constructor: /** * Constructor */function __construct(){ global $mainframe; parent::__construct(); // Get the pagination request variables $limit = $mainframe->getUserStateFromRequest( 'global.list.limit', 'limit', $mainframe->getCfg('list_limit')); $limitstart = $mainframe->getUserStateFromRequest( $option.'limitstart', 'limitstart', 0); // Set the state pagination variables $this->setState('limit', $limit); $this->setState('limitstart', $limitstart);} Remember that $mainframe references the global JApplication object. We use the getUserStateFromRequest() method to get the limit and limitstart variables. We use the user state variable, global.list.limit, to determine the limit. This variable is used throughout Joomla! to determine the length of lists. For example, if we were to view the Article Manager and select a limit of five items per page, if we move to a different list it will also be limited to five items. If a value is set in the request value limit (part of the listFooter), we use that value. Alternatively we use the previous value, and if that is not set we use the default value defined in the application configuration. The limitstart variable is retrieved from the user state value $option, plus .limitstart. The $option value holds the component name, for example com_content. If we build a component that has multiple lists we should add an extra level to this, which is normally named after the entity. If a value is set in the request value limitstart (part of the listFooter) we use that value. Alternatively we use the previous value, and if that is not set we use the default value 0, which will lead us to the first page. The reason we retrieve these values in the constructor and not in another method is that in addition to using these values for the JPagination object, we will also need them when getting data from the database. In our existing component model we have a single method for retrieving data from the database, getRevues(). For reasons that will become apparent shortly we need to create a private method that will build the query string and modify our getRevues() method to use it. /** * Builds a query to get data from #__boxoffice_revues * @return string SQL query */function _buildQuery(){ $db =& $this->getDBO(); $rtable = $db->nameQuote('#__boxoffice_revues'); $ctable = $db->nameQuote('#__categories'); $query = ' SELECT r.*, cc.title AS cat_title' . ' FROM ' . $rtable. ' AS r' . ' LEFT JOIN '.$ctable.' AS cc ON cc.id=r.catid; return $query;} We now must modify our getRevues() method: /** * Get a list of revues * * @access public * @return array of objects */function getRevues(){ // Get the database connection $db =& $this->_db; if( empty($this->_revues) ) { // Build query and get the limits from current state $query = $this->_buildQuery(); $limitstart = $this->getState('limitstart'); $limit = $this->getState('limit'); $this->_revues = $this->_getList($query, $limitstart, $limit); } // Return the list of revues return $this->_revues;} We retrieve the object state variables limit and limitstart and pass them to the private JModel method _getList(). The _getList() method is used to get an array of objects from the database based on a query and, optionally, limit and limitstart. The last two parameters will modify the first parameter, a query, in such a way that we only return the desired results. For example if we requested page 1 and were displaying a maximum of five items per page, the following would be appended to the query: LIMIT 0, 5. To handle pagination we need to add a method called getPagination() to our model. This method will handle items we are trying to paginate using a JPagination object. Here is our code for the getPagination() method: /** * Get a pagination object * * @access public * @return pagination object */function getPagination(){ if (empty($this->_pagination)) { // Import the pagination library jimport('joomla.html.pagination'); // Prepare the pagination values $total = $this->getTotal(); $limitstart = $this->getState('limitstart'); $limit = $this->getState('limit'); // Create the pagination object $this->_pagination = new JPagination($total, $limitstart, $limit); } return $this->_pagination;} There are three important aspects to this method. We use the private property $_pagination to cache the object, we use the getTotal() method to determine the total number of items, and we use the getState() method to determine the number of results to display. The getTotal() method is a method that we must define in order to use. We don't have to use this name or this mechanism to determine the total number of items. Here is one way of implementing the getTotal() method: /** * Get number of items * * @access public * @return integer */function getTotal(){ if (empty($this->_total)) { $query = $this->_buildQuery(); $this->_total = $this->_getListCount($query); } return $this->_total;} This method calls our model's private method _buildQuery() to build the query, the same query that we use to retrieve our list of revues. We then use the private JModel method _getListCount()to count the number of results that will be returned from the query. We now have all we need to be able to add pagination to our revues list except for actually adding pagination to our list page. We need to add a few lines of code to our revues/view.html.php file. We will need to access to global user state variables so we must add a reference to the global application object as the first line in our display method: global $mainframe; Next we need to create and populate an array that will contain user state information. We will add this code immediately after the code that builds the toolbar: // Prepare list array$lists = array();// Get the user state$filter_order = $mainframe->getUserStateFromRequest( $option.'filter_order', 'filter_order', 'published');$filter_order_Dir = $mainframe->getUserStateFromRequest( $option.'filter_order_Dir', 'filter_order_Dir', 'ASC');// Build the list array for use in the layout$lists['order'] = $filter_order;$lists['order_Dir'] = $filter_order_Dir;// Get revues and pagination from the model$model =& $this->getModel( 'revues' );$revues =& $model->getRevues();$page =& $model->getPagination();// Assign references for the layout to use$this->assignRef('lists', $lists);$this->assignRef('revues', $revues);$this->assignRef('page', $page); After we create and populate the $lists array, we add a variable $page that receives a reference to a JPagination object by calling our model's getPagination() method. And finally we assign references to the $lists and $page variables so that our layout can access them. Within our layout default.php file we must make some minor changes toward the end of the existing code. Between the closing </tbody> tag and the </table> tag we must add the following: <tfoot> <tr> <td colspan="10"> <?php echo $this->page->getListFooter(); ?> </td> </tr></tfoot> This creates the pagination footer using the JPagination method getListFooter(). The final change we need to make is to add two hidden fields to the form. Under the existing hidden fields we add the following code: <input type="hidden" name="filter_order" value="<?php echo $this->lists['order']; ?>" /><input type="hidden" name="filter_order_Dir" value="" /> The most important thing to notice is that we leave the value of the filter_order_Dir field empty. This is because the listFooter deals with this for us. That is it! We now have added pagination to our page. Ordering Another enhancement that we can add is the ability to sort or order our data by column, which we can accomplish easily using the JHTML grid.sort type. And, as an added bonus, we have already completed a significant amount of the necessary code when we added pagination. Most of the changes to revues/view.html.php that we made for pagination are used for implementing column ordering; we don't have to make a single change. We also added two hidden fields, filter_order and filter_order_Dir, to our layout form, default.php. The first defines the column to order our data and the latter defines the direction, ascending or descending. Most of the column headings for our existing layout are currently composed of simple text wrapped in table heading tags (<th>Title</th> for example). We need to replace the text with the output of the grid.sort function for those columns that we wish to be orderable. Here is our new code: <thead> <tr> <th width="20" nowrap="nowrap"> <?php echo JHTML::_('grid.sort', JText::_('ID'), 'id', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="20" nowrap="nowrap"> <input type="checkbox" name="toggle" value="" onclick="checkAll( <?php echo count($this->revues); ?>);" /> </th> <th width="40%"> <?php echo JHTML::_('grid.sort', JText::_('TITLE'), 'title', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="20%"> <?php echo JHTML::_('grid.sort', JText::_('REVUER'), 'revuer', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="80" nowrap="nowrap"> <?php echo JHTML::_('grid.sort', JText::_('REVUED'), 'revued', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="80" nowrap="nowrap" align="center"> <?php echo JHTML::_('grid.sort', 'ORDER', 'ordering', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="10" nowrap="nowrap"> <?php if($ordering) echo JHTML::_('grid.order', $this->revues); ?> </th> <th width="50" nowrap="nowrap"> <?php echo JText::_('HITS'); ?> </th> <th width="100" nowrap="nowrap" align="center"> <?php echo JHTML::_('grid.sort', JText::_('CATEGORY'), 'category', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> <th width="60" nowrap="nowrap" align="center"> <?php echo JHTML::_('grid.sort', JText::_('PUBLISHED'), 'published', $this->lists['order_Dir'], $this->lists['order'] ); ?> </th> </tr></thead> Let's look at the last column, Published, and dissect the call to grid.sort. Following grid.sort we have the name of the column, filtered through JText::_() passing it a key to our translation file. The next parameter is the sort value, the current order direction, and the current column by which the data is ordered. In order for us to be able to use these headings to order our data we must make a few additional modifications to our JModel class. We created the _buildQuery() method earlier when we were adding pagination. We now need to make a change to that method to handle ordering: /** * Builds a query to get data from #__boxoffice_revues * @return string SQL query */function _buildQuery(){ $db =& $this->getDBO(); $rtable = $db->nameQuote('#__boxoffice_revues'); $ctable = $db->nameQuote('#__categories'); $query = ' SELECT r.*, cc.title AS cat_title' . ' FROM ' . $rtable. ' AS r' . ' LEFT JOIN '.$ctable.' AS cc ON cc.id=r.catid' . $this->_buildQueryOrderBy(); return $query;} Our method now calls a method named _buildQueryOrderBy() that builds the ORDER BY clause for the query: /** * Build the ORDER part of a query * * @return string part of an SQL query */function _buildQueryOrderBy(){ global $mainframe, $option; // Array of allowable order fields $orders = array('title', 'revuer', 'revued', 'category', 'published', 'ordering', 'id'); // Get the order field and direction, default order field // is 'ordering', default direction is ascending $filter_order = $mainframe->getUserStateFromRequest( $option.'filter_order', 'filter_order', 'ordering'); $filter_order_Dir = strtoupper( $mainframe->getUserStateFromRequest( $option.'filter_order_Dir', 'filter_order_Dir', 'ASC')); // Validate the order direction, must be ASC or DESC if ($filter_order_Dir != 'ASC' && $filter_order_Dir != 'DESC') { $filter_order_Dir = 'ASC'; } // If order column is unknown use the default if (!in_array($filter_order, $orders)) { $filter_order = 'ordering'; } $orderby = ' ORDER BY '.$filter_order.' '.$filter_order_Dir; if ($filter_order != 'ordering') { $orderby .= ' , ordering '; } // Return the ORDER BY clause return $orderby;} As with the view, we retrieve the order column name and direction using the application getUserStateFromRequest() method. Since this data is going to be used to interact with the database, we perform some data sanity checks to ensure that the data is safe to use with the database. Now that we have done this we can use the table headings to order itemized data. This is a screenshot of such a table: Notice that the current ordering is title descending, as denoted by the small arrow to the right of Title.
Read more
  • 0
  • 0
  • 2596

article-image-drools-jboss-rules-50-flow-part-2
Packt
16 Oct 2009
8 min read
Save for later

Drools JBoss Rules 5.0 Flow (Part 2)

Packt
16 Oct 2009
8 min read
Transfer Funds work item We'll now jump almost to the end of our process. After a loan is approved, we need a way of transferring the specified sum of money to customer's account. This can be done with rules, or even better, with pure Java as this task is procedural in nature. We'll create a custom work item so that we can easily reuse this functionality in other ruleflows. Note that if it was a once-off task, it would probably be better suited to an action node. The Transfer Funds node in the loan approval process is a custom work item. A new custom work item can be defined using the following four steps (We'll see how they are accomplished later on): Create a work item definition. This will be used by the Eclipse ruleflow editor and by the ruleflow engine to set and get parameters. For example, the following is an extract from the default WorkDefinitions.conf file that comes with Drools. It describes 'Email' work definition. The configuration is written in MVEL. MVEL allows one to construct complex object graphs in a very concise format. This file contains a list of maps—List<map<string, Object>>. Each map defines properties of one work definition. The properties are: name, parameters (that this work item works with), displayName, icon, and customEditor (these last three are used when displaying the work item in the Eclipse ruleflow editor). A custom editor is opened after double-clicking on the ruleflow node. import org.drools.process.core.datatype.impl.type.StringDataType;[ [ "name" : "Email", "parameters" : [ "From" : new StringDataType(), "To" : new StringDataType(), "Subject" : new StringDataType(), "Body" : new StringDataType() ], "displayName" : "Email", "icon" : "icons/import_statement.gif", "customEditor" : "org.drools.eclipse.flow.common.editor. editpart.work.EmailCustomEditor" ]] Code listing 13: Excerpt from the default WorkDefinitions.conf file. Work item's parameters property is a map of parameterName and its value wrappers. The value wrapper must implement the org.drools.process.core.datatype.DataType interface. Register the work definitions with the knowledge base configuration. This will be shown in the next section. Create a work item handler. This handler represents the actual behavior of a work item. It will be invoked whenever the ruleflow execution reaches this work item node. All of the handlers must extend the org.drools.runtime.process.WorkItemHandler interface. It defines two methods. One for executing the work item and another for aborting the work item. Drools comes with some default work item handler implementations, for example, a handler for sending emails: org.drools.process.workitem.email.EmailWorkItemHandler. This handler needs a working SMTP server. It must be set through the setConnection method before registering the work item handler with the work item manager (next step). Another default work item handler was shown in code listing 2 (in the first part)-SystemOutWorkItemHandler. Register the work item handler with the work item manager. After reading this you may ask, why doesn't the work item definition also specify the handler? It is because a work item can have one or more work item handlers that can be used interchangeably. For example, in a test case, we may want to use a different work item handler than in production environment. We'll now follow this four-step process and create a Transfer Funds custom work item. Work item definition Our transfer funds work item will have three input parameters: source account, destination account, and the amount to transfer. Its definition is as follows: import org.drools.process.core.datatype.impl.type.ObjectDataType;[ [ "name" : "Transfer Funds", "parameters" : [ "Source Account" : new ObjectDataType("droolsbook.bank. model.Account"), "Destination Account" : new ObjectDataType("droolsbook.bank. model.Account"), "Amount" : new ObjectDataType("java.math.BigDecimal") ], "displayName" : "Transfer Funds", "icon" : "icons/transfer.gif" ]] Code listing 14: Work item definition from the BankingWorkDefinitions.conf file. The Transfer Funds work item definition from the code above declares the usual properties. It doesn't have a custom editor as was the case with email work item. All of the parameters are of the ObjectDataType type. This is a wrapper that can wrap any type. In our case, we are wrapping Account and BigDecimal  types. We've also specified an icon that will be displayed in the ruleflow's editor palette and in the ruleflow itself. The icon should be of the size 16x16 pixels. Work item registration First make sure that the BankingWorkDefinitions.conf file is on your classpath. We now have to tell Drools about our new work item. This can be done by creating a drools.rulebase.conf file with the following contents: drools.workDefinitions = WorkDefinitions.conf BankingWorkDefinitions.conf Code listing 15: Work item definition from the BankingWorkDefinitions.conf file (all in one one line). When Drools starts up, it scans the classpath for configuration files. Configuration specified in the drools.rulebase.conf file will override the default configuration. In this case, only the drools.workDefinitions setting is being overridden. We already know that the WorkDefinitions.conf file contains the default work items such as email and log. We want to keep those and just add ours. As can be seen from the code listing above, drools.workDefinitions settings accept list of configurations. They must be separated by a space. When we now open the ruleflow editor in Eclipse, the ruleflow palette should contain our new Transfer Funds work item. If you want to know more about the file based configuration resolution process, you can look into the org.drools.util.ChainedProperties class. Work item handler Next, we'll implement the work item handler. It must implement the org. drools.runtime.process.WorkItemHandler interface that defines two methods: executeWorkItem and abortWorkItem. The implementation is as follows: /** * work item handler responsible for transferring amount from * one account to another using bankingService.transfer method * input parameters: 'Source Account', 'Destination Account' * and 'Amount' */public class TransferWorkItemHandler implements WorkItemHandler { BankingService bankingService; public void executeWorkItem(WorkItem workItem, WorkItemManager manager) { Account sourceAccount = (Account) workItem .getParameter("Source Account"); Account destinationAccount = (Account) workItem .getParameter("Destination Account"); BigDecimal sum = (BigDecimal) workItem .getParameter("Amount"); try { bankingService.transfer(sourceAccount, destinationAccount, sum); manager.completeWorkItem(workItem.getId(), null); } catch (Exception e) { e.printStackTrace(); manager.abortWorkItem(workItem.getId()); } } /** * does nothing as this work item cannot be aborted */ public void abortWorkItem(WorkItem workItem, WorkItemManager manager) { } Code listing 16: Work item handler (TransferWorkItemHandler.java file). The executeWorkItem method retrieves the three declared parameters and calls the bankingService.transfer method (the implementation of this method won't be shown). If all went OK, the manager is notified that this work item has been completed. It needs the ID of the work item and optionally a result parameter map. In our case, it is set to null. If an exception happens during the transfer, the manager is told to abort this work item. The abortWorkItem method on our handler doesn't do anything because this work item cannot be aborted. Please note that the work item handler must be thread-safe. Many ruleflow instances may reuse the same work item instance. Work item handler registration The transfer work item handler can be registered with a WorkItemManager as follows: TransferWorkItemHandler transferHandler = new TransferWorkItemHandler(); transferHandler.setBankingService(bankingService); session.getWorkItemManager().registerWorkItemHandler( "Transfer Funds", transferHandler); Code listing 17: TransferWorkItemHandler registration (DefaultLoanApprovalServiceTest.java file). A new instance of this handler is created and the banking service is set. Then it is registered with WorkItemManager in a session. Next, we need to 'connect' this work item into our ruleflow. This means set its parameters once it is executed. We need to set the source/destination account and the amount to be transferred. We'll use the in-parameter mappings of Transfer Funds to set these parameters. As we can see the Source Account is mapped to the loanSourceAccount ruleflow variable. The Destination Account ruleflow variable is set to the destination account of the loan and the Amount ruleflow variable is set to loan amount. Testing the transfer work item This test will verify that the Transfer Funds work item is correctly executed with all of the parameters set and that it calls the bankingService.transfer method with correct parameters. For this test, the bankingService service will be mocked with jMock library (jMock is a lightweight Mock object library for Java. More information can be found at http://www.jmock.org/). First, we need to set up the banking service mock object in the following manner: mockery = new JUnit4Mockery();bankingService = mockery.mock(BankingService.class); Code listing 18: jMock setup of bankingService mock object (DefaultLoanApprovalServiceTest.java file). Next, we can write our test. We are expecting one invocation of the transfer method with loanSourceAccount and loan's destination and amount properties. Then the test will set up the transfer work item as in code listing 17, start the process, and approve the loan (more about this is discussed in the next section). The test also verifies that the Transfer Funds node has been executed. Test method's implementation is as follows: @Test public void transferFunds() { mockery.checking(new Expectations() { { one(bankingService).transfer(loanSourceAccount, loan.getDestinationAccount(), loan.getAmount()); } }); setUpTransferWorkItem(); setUpLowAmount(); startProcess(); approveLoan(); assertTrue(trackingProcessEventListener.isNodeTriggered( PROCESS_LOAN_APPROVAL, NODE_WORK_ITEM_TRANSFER)); } Code listing 19: Test for the Transfer Funds work item (DefaultLoanApprovalServiceTest.java file). The test should execute successfully.
Read more
  • 0
  • 0
  • 2594
article-image-development-windows-mobile-applications-part-2
Packt
26 Oct 2009
3 min read
Save for later

Development of Windows Mobile Applications (Part 2)

Packt
26 Oct 2009
3 min read
Now let us see how to deploy it on Windows Mobile Device. For deploying the application on device you need to have ActiveSync installed. There are two ways in which application can be deployed on to the device.  First option is to connect the device to the Development machine via USB. ActiveSync will automatically detect it and you can click on on the top bar. And this time select option "Windows Mobile 6 Professional Device". But then this approach is useful when you want to test/deploy and use the application yourself. What if you want to distribute it to others? In that case you need to create an installation program for your Windows mobile application. The installation file in the Windows Mobile world is distributed in the form of a CAB file. So once we have done with application we should opt for option 2 of creating a CAB file (A CAB file is a library of compressed files stored as a single file). Creating CAB File Creating a CAB file itself is a new project. To create CAB project right click on the solution and select the option New Project as shown below. Clicking on New Project option will open Add New Project Wizard. Select option Setup and Deployment under Other Project Types on the left hand menu. Then select option Smart Device CAB Project on right hand side as shown below. We have named this project as MyFirstAppCAB. Click OK and MyFirstAppCAB project is created under the solution a shown. Now to add files to the CAB, right click on the Application Folder under File System on Target Machine and select option Add-> Project Output as shown. On selecting Project Output option, the following screen will popup. Depending upon the requirement, select what all needs to be compressed in CAB file. For this example we require only output, hence will select option Primary output. Now right click on CAB project MyFirstAppCAB and select option Build. CAB file with name MyFirstAppCAB will be created at the location MyFirstAppMyFirstAppCABDebug. Now let us see how we can deploy this CAB file on emulator and run the application. Click on Tools on the top bar and select option Device Emulator Manager. This will open a Device Emulator Manager as shown below. Select option Windows Mobile 6 Classic Emulator. Right click and select option Connect. Windows Mobile Emulator will start and on Device Emulator Manager you can see to left of Windows Mobile 6 Classic Emulator as shown below. Next step is to Cradle. If you are attempting to cradle for the 1st time, then you need to setup ActiveSync. To setup ActiveSync, double click on on right bottom on Task bar. Microsoft ActiveSync will open up, select option File -> Connection Settings as shown in figure below. Connection Settings window will be open up as shown below. Check the option Allow Connections to one of the followings and then from the drop down select the option DMA. After connecting Windows Mobile 6 Classic Emulator using Device Emulator Manager, again right click and select option Cradle as shown below. Cradle will start ActiveSync and make Emulator work as device connected using ActiveSync. On successful connection you can see on the left of option Windows Mobile 6 Classic Emulator on Device Emulator Manager as shown.
Read more
  • 0
  • 0
  • 2593

article-image-google-apps-surfing-web
Packt
13 Dec 2011
8 min read
Save for later

Google Apps: Surfing the Web

Packt
13 Dec 2011
8 min read
Browsing and using websites Back in the day, when I first started writing, there were two ways to research—own a lot of books (I did and still do), and/or spend a lot of time at the library (I did, don't have to now). This all changed in the early 90s when Sir Tim Berners-Lee invented the World Wide Web (WWW) . The web used the Internet, which was already there, although Al Gore did not invent the Internet. Although earlier experiments took place, Vinton Cerf's development of the basic transmission protocols making all we enjoy today possible gives him the title "Father of the Internet". All of us reading this book use the Internet and the web almost every day. App Inventor itself relies extensively on the web; you have to use the web in designing apps and downloading the Blocks Editor to power them up. Adding web browsing to our apps gives us: Access to literally trillions of web pages (no one knows how many; Google said it was over a trillion in 2008, and growth has been tremendous since then). Lets us leverage the limited resources and storage capacity of the user's phone by many times as we use the millions of dollars invested in server farms (vast collections of interconnected computers) and thousands of web pages on commercial sites (which they want us to use, even beg us to use because it promotes their products or services). Makes it possible to write powerful and useful apps with really little effort on our part. Take, for example, what I referred to earlier in this book as a link app. This is an app that, when called by the user, simply uses ActivityStarter to open a browser and load a web page. Let's whip one up. Time for action – building an eBay link app Yes, eBay loves us—especially if we buy or sell items on this extensive online auction site. And they want you to do it not just at home but when you're out with only your smartphone. To encourage use from your phone, eBay has spent a gazillion dollars (that's a lot) in providing a mobile site (http://m.ebay.com) that makes the entire eBay site (hundreds of thousands, probably millions of pages) available and useful to you. Back to that word, leverage—the ancient Greek mathematician, Archimedes, said about levers, "Give me a place to stand on and I will move the Earth." Our app's leverage won't move the Earth, but we can sure bid on just about everything on it. Okay, the design of our eBay app is very simple since the screen will be there for only a second or so. I'll explain that in a moment. So, we need just a label and two non-visual components: ActivityStarter and Clock. In the Properties column for the ActivityStarter, put android.intent.action.VIEW in the Action field (again, this is how your app calls the phone's web browser, and the way it's entered is case-sensitive). This gives us something as shown in the following screenshot (with a little formatting added): Now, the reason for the LOADING...nInternet connection required (in the label, n being a line break) is a basic notifier and error trap. First, if the Internet connection is slow, it lets the user know something is happening. Second, if there is not 3G or Wi-Fi connection, it tells the user why nothing will happen until they get a connection. Simple additions like the previous (basically thinking of the user's experience in using our apps) define the difference between amateur and professional apps. Always try to anticipate, because if we leave any way possible at all to screw it up, some user will find it. And who gets blamed? Right. You, me, or whatever idiot wrote that defective app. And they will zing you on Android Market. Okay, now to our buddy: the Blocks Editor. We need only one small block group. Everything is in the Clock1.Timer block to connect to the eBay mobile site and then, job done, gracefully exit. Inside the clock timer frame, we put four blocks, which accomplish the following logic: In our ActivityStarter1.DataUri goes the web address of the eBay mobile website home: http://m.ebay.com. The ActivityStarter1.StartActivity block calls the phone's web browser and passes the address to it. Clock1.TimerAlwaysFires set to false tells AI, "Stop, don't do anything else." Finally, the close application block (which we should always be nice and include somewhere in our apps) removes the app from the phone or other Android device's memory, releasing those always scarce resources. Make a nice icon, and it's ready to go onto Android Market (I put mine on as eBay for Droids). What just happened? That's it—a complete application giving access to a few million great bargains on eBay. This is how it will look when the eBay mobile site home page opens on the user's phone: Pretty neat, huh? And there are lots of other major sites out there that offer mobile sites, easily converted into link apps such as this eBay example. But, what if you want to make the app more complex with a lot of choices? One that after the user finishes browsing a site, they come back to your app and choose yet another site to visit? No problem. Here's an example of that. I recently published an app called AVLnews (AVL is the airport code for Asheville, North Carolina where I live). This app actually lets the user drill down into local news for all 19 counties in the Western North Carolina mountains. Here's what the front page of the app looks like: Even with several pages of choices, this type of app is truly easy to create. You need only a few buttons, labels, and (as ever) horizontal and vertical arrangements for formatting. And, of course, add a single ActivityStarter for calling the phone's web browser. Now, here's the cool part! No matter how long and how many pages your user reads on the site a button sends him to, when he or she hits the hardware Back button on their phone, they return to your app. The preceding is the only way the Back button works for an App Inventor app! If user is within an AI app and hits the Back button, it immediately kills your app (except when a listpicker is displayed, in which case it returns you to the screen that invoked it). This is doubleplusungood, so to speak. So, always supply navigation buttons for changing pages and maybe a note somewhere not to use the hardware button. Okay, back to my AVLnews app as an example. The first button I built was for the Citizen-Times, our major newspaper in the area. They have a mobile site such as the one we saw earlier for eBay. It looks nice and is easy to read on a Droid or other smartphone, like the following: And, it's equally easy to program—this is all you need: I then moved on to other news sources for the areas. The small weekly newspapers in the more isolated, outlying mountain counties have no expensive mobile sites. The websites they do have are pretty conventional. But, when I linked to them, the page would come up with tiny, unreadable type. I had to move it around, do the double tap on the content to fit to the page trick to expand the page, turn the phone on its side, and many such more, and still had trouble reading stuff. Folks, you do not do things like that to your users. Not if you want them to think you are one cool app inventor, as I know you to be by now. So, here's the trick to making almost all web pages readable on a phone—Google Mobilizer! It's a free service of Google at http://www.google.com/gwt/n. Use it to construct links that return a nicely formatted and readable page as shown in the next screenshot. People will thank you for it and think you expended many hours of genius-level programming effort to achieve it. And, remember, it's not polite to disagree with people, eh? Often, the search terms and mobilizing of your link is long and goes on for some time (the following screenshot is only a part of it). However, that's where your real genius comes into play: building a search term that gets the articles fitting whatever is the topic on the button. Summing up: using the power of the web lets us build powerful apps that use few resources on the phone yet return thousands upon thousands of pages. Enjoy. Now, we will look at yet another Google service: Fusion Tables. And see how our App Inventor apps can take advantage of these online data sources.  
Read more
  • 0
  • 0
  • 2591
Modal Close icon
Modal Close icon