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-working-events-mootools-part-2
Packt
07 Jan 2010
10 min read
Save for later

Working with Events in MooTools: Part 2

Packt
07 Jan 2010
10 min read
Removing, Cloning, and Firing off Events Besides adding event listeners, other operations you may want to do are removing events from an element, cloning events from other elements, and firing off events for elements manually. We'll go through each one of these operations. Removing events from elements There are instances when you want to remove an event listener that you've added to an element. One reason would be that you only want to an element to be triggered once, and after that event has been triggered, you no longer want to trigger it again. To ensure it only fires once, you should remove the event once certain conditions have been met. Removing a single event from elements There are two methods available to you for removing events from elements. The first is removeEvent() which removes a single specified event. Time for action – removing an event Let's say you have some hyperlinks on a page, that when clicked, will alert the user that they have clicked a hyperlink, but you only wanted to do it once. To ensure that the warning message appears only once, we'll have to remove the event after it has been fired. This type of thing may be utilized for instructional tips: when the user sees an unfamiliar interface element, you can display a help tip for them, but only once - because you don't want the tip to keep showing up every single time they perform an action. First, let's put some links on a web page. <a href="#">Hyperlink 1</a> <a href="#">Hyperlink 2</a> Next, let's create a function object that we will call whenever a click event happens on any of the links on our page. When the function fires, it will open up an alert box with a message, and then it will remove the click event  from all <a> elements on the web page. // Create an function objectvar warning = function() { alert('You have clicked a link. This is your only warning'); // After warning has executed, remove it $$('a').removeEvent('click', warning);}; Now we add a click event listener that will fire off the warning function object. // Add a click event listener which when triggered, executes the //warning function$$('a').addEvent('click', warning); Our script should look like the following window.addEvent('domready', function(){ // Create an function object that will be executed when a //click happens var warning = function() { alert('You have clicked a link. This is your only warning'); // After warning has executed, remove it from all <a> //elements on the web page $$('a').removeEvent('click', warning); }; // Add a click event listener which when triggered, executes the //warning function $$('a').addEvent('click', warning);}); Test in your web browser by clicking on any of the hyperlinks on the page. The first time you click, you'll see an alert dialog box with our message. The second (or third, forth, fifth… you get the picture) time you click on any hyperlink, the alert dialog box will no longer show up. Removing a type of event, or all events, from elements If you want to remove a type of event on an element (or set of elements), or if you want to remove all events regardless of its type from an element, you have to use the removeEvents method. To remove a type of event from an element, you pass the type of event you want to remove as a parameter of the removeEvents method. For example, if you wanted to remove all click events that were added using MooTools addEvent method from an element called myElement, you would do the following: $('myElement').removeEvents('click'); If instead, you wanted to remove all events that myElement has regardless of the type of event it has, then you would simply run removeEvents as follows: $('myElement').removeEvents(); Cloning events from another element What if you wanted to copy all event listeners from another element. This could be useful in situations where you clone an element using the clone MooTools element method. Cloning an element doesn't copy the event listeners attached to it, so you also have to run the cloneEvents method on the element being cloned if you wanted to also port the event listeners to the copy. To clone the events of an element, follow the format: // clone the elementvar original = $(‘originalElement’);var myClone = original.clone();// clone the events from the originalmyClone.cloneEvents(original); Firing off Events Sometimes you want to fire off events manually. This is helpful in many situations, such as manually firing off an event listener functions that is triggered by another event. For example, to fire off a click event on myElement without having the user actually clicking on myElement, you would do the following: $('myElement').fireEvent('click'); Time for action – firing off a click event Imagine that you have a hyperlink with a click event listener attached to it, that when triggered, alerts the user with a message. But you also want to fire off this alert message when the user presses the Ctrl key. Here's how you'd do this: First, let us place a hyperlink in an HTML document. We'll put it inside a <p> element and tell the users that clicking on the hyperlink or pressing the Ctrl key will open up an alert dialog box. <body> <p>Show a warning by clicking on this link: <a href="#">Click me</a>. Alternatively, you can show the warning by pressing the <strong>Ctrl</strong> key on your keyboard.</p></body> Next, let's add an event to <a> elements. We'll use the addEvent method to do this. // Add a click event$$('a').addEvent('click', function(){ alert('You either clicked a link or pressed the Ctrl key.');}); Now we have to add another event listener onto our HTML document that watches out for a keydown event. The function that the event listener executes will check if the key pressed is the Ctrl key by using the control Event method which returns a Boolean value of true if the Ctrl key is pressed. If the key that was pressed is the Ctrl key, we ask it to fire the click event function that we set in all our a elements by using the fireEvent method with click as its parameter. // Add a keydown event on our web pagewindow.addEvent('keydown', function(e){// If the keypress is the Ctrl key // manually fire off the click event if(e.control) { $$('a').fireEvent('click'); }}); All together, our MooTools script should look like this: window.addEvent('domready', function(){ // Add a click event $$('a').addEvent('click', function(){ alert('You either clicked a link or pressed the Ctrl key.'); }); // Add a keydown event on our web page window.addEvent('keydown', function(e){ // If the keypress is the Ctrl key // manually fire off the click event if(e.control) { $$('a').fireEvent('click'); } });}); Test your HTML document in the web browser. Click on the “Click me” link. It should show you the alert message we created. Press the Ctrl key as well. It should also open up the same alert message we created. The MooTools Event Object The MooTools Event object, which is part of the Native component, is what allows us to create and work with events. It's therefore worth it to take a bit of time to explore the Events object. Using Event Object Methods There are three Event methods: preventDefault, stopPropagation, stop. Preventing the default behavior Events usually has a default behavior; that is, it has a predefined reaction in the instance that the event is triggered. For example, clicking on a hyperlink will direct you to the URL that href property is assigned to. Clicking on a submit input field will submit the form to the value that the action property of the form element is assigned to. Perhaps you want to open the page in a new window, but instead of using the non-standard target property on an <a> element, you can use JavaScript to open the page in a new window. Or maybe you need to validate a form before submitting it. You will want to prevent the default behaviors of an event doing either one of these things. You can use the preventDefault method to do so. Time for action – preventing the default behavior of a hyperlink Imagine that you have a list of hyperlinks that go to popular sites. The thing is, you don't want your website visitors to ever get to see them (at least coming from your site). You can prevent the default behavior of your hyperlinks using the preventDefault method. Here is the HTML markup for a list of <a> elements that go to popular websites. Place it inside an HTML document. <h1>A list of links you can't go to.</h1><ul> <li><a href="http://www.google.com/">Google</a></li> <li><a href="http://www.yahoo.com/">Yahoo!</a></li> <li><a href="http://digg.com/">Digg</a></li> </ul> We will warn the user with an alert dialog box that tells them they can't access the links, even when they click on it. We'll fire this alert dialog box when a user clicks on it. Notice the e argument in the function? That is the event object that is passed into the function, allowing us to access events' methods and properties. $$('a').addEvent('click', function(e){alert('Sorry you can't go there. At least not from this page.'); }); Open your HTML document in a web browser and verify that the links still open their destination, since we haven't prevented the default yet. You will, however, see the alert dialog box we set up in step 2, showing you that, indeed, the click event listener function fires off. Now we will prevent the links from opening by using the preventDefault method. We'll just add the following line above the alert(); line: e.preventDefault(); Test the document again in your web browser. Clicking on any hyperlink opens the alert dialog box, but doesn't open the hyperlink. Preventing event bubbling Event bubbling occurs when you have an element inside another element. When an event is triggered from the child element, the same event is triggered for the parent element, with the child element taking precedence by being triggered first. You can prevent event bubbling using the stopPropagation method. Let's explore the concept of event bubbling and how to prevent it from occurring (if you want to), using the stopPropagation event method.
Read more
  • 0
  • 0
  • 4045

article-image-enhancing-your-math-teaching-using-moodle-19-part-1
Packt
06 Jan 2010
6 min read
Save for later

Enhancing Your Math Teaching using Moodle 1.9: Part 1

Packt
06 Jan 2010
6 min read
There are many topics to explore in this article, so let's make a start with mathematical PowerPoint presentations. PowerPoint and Mathematics We have already seen how we can use the Microsoft Equation Editor to include mathematics notation in Microsoft Word documents (we copied them from the document into our Moodle course). Microsoft PowerPoint also includes the Equation Editor, and we can use this facility to create some quite elegant online explanations of difficult mathematical ideas. Here is a quick recap (using Microsoft PowerPoint instead of Microsoft Word): Click the slide to which you want to add an equation. On the Insert menu, click Object. In the Object type list, click Microsoft Equation 3.0 (if Microsoft Equation 3.0 is not listed, then you will need to install it. See http://support.microsoft.com/kb/228569). In the Equation Editor, use the buttons and menus to type your equation. To return to Microsoft PowerPoint, on the File menu in Equation Editor, click Exit. The equation will now be included on your slide. Add a special Equation Editor button to any Microsoft Office application toolbar. For example in Office 2003, in the View menu, point to Toolbars, and then click Customize. Click the Commands tab, and in the Categories list, click Insert. In the Commands box, click Equation Editor, and then drag it from the Commands box to a gray area within any toolbar. Then click Close. Click on the new toolbar button to install and display the Equation Editor. Quickly crafting a Pythagorean PowerPoint I'm guessing you're going to be fairly familiar with PowerPoint, so let's make a start by creating a basic presentation, showing our students how they can transpose/rearrange an equation. I'm going to be showing my students how they can find the missing length in a right-angled triangle. Note that I'm an Office 2003 user running Windows Vista. If you aren't using the same version of Office or the same operating system as me, then as you follow my examples your screen might look different from mine: The first step is to create a new presentation. For the first page of this presentation, I've added a new slide and used the Title, Text, and Content layout: I've searched for a Creative Commons image of a ladder on Flickr and drawn a schematic using Microsoft PowerPoint's built-in drawing tools. Here is the completed slide: In the next slides, let's demonstrate how we can turn the ladder problem into a Pythagorean Theorem/algebra problem (without being too scary about the algebra). Let's animate the slide to allow the students to recall the theorem: Now, allow the students to check if they got it right. Right-click on an object and select Custom Animation… to make the presentation a little more interactive: Now I've recalled the Pythagorean Theorem, which I need to relate back to the ladder problem. Again, I've used animations to make the slide interactive: I'm going to complete the presentation by giving my students a little guidance on algebraic transposition and then that's it—I'm done! I hope you'll agree that with some simple custom animations we've made this PowerPoint far more engaging and entertaining than it would otherwise be. Want to avoid creating a truly boring PowerPoint presentation? Navigate your browser to http://www.youtube.com and search for Don McMillan's video on how NOT to use PowerPoint! Uploading to Moodle I could simply upload the PowerPoint as is to my course files area, but I'm a bit worried that without my describing what's going on in the presentation, it isn't going to make a lot of sense to my students. To overcome this problem, I'm going to record an audio commentary. You can insert sound directly into your slides either from the main menu (Insert) or via the Insert tab in Microsoft PowerPoint 2007's ribbon. Providing an audio commentary The presentation I crafted in the previous section is fine on its own, and I do use something similar as part of my face-to-face teaching. But I want my students to be able to study this example in their own time and, to that end, I would like to enhance it with an audio commentary. There are three basic ways I can achieve this (aside from inserting audio into each slide). Each has its own advantages and disadvantages: Record a separate audio track and allow the students to listen to the audio following the presentation at their own pace—almost like a read-along story Upload the presentation to SlideShare and use SlideShare's built-in audio recording tools to narrate the PowerPoint Record a screencast. Either upload it directly to our Moodle course or to a content sharing website (that is, YouTube or TeacherTube) In the following sections we'll investigate each option in turn. Recording a separate narration—using Audacity to narrate a slideshow A great way to record a narration is by using Audacity. Audacity is an extremely popular, free recording and audio editing tool. Download the latest version from http://audacity.sourceforge.net/download/. Once you have Audacity installed, it is very easy to use. Let's record a narration: The first task, before we begin recording, is to write a script. There's nothing worse than listening to a badly prepared or rambling presentation, so let's make sure it's tightly scripted: When you are ready to begin recording your commentary, press Audacity's "record" button: When you are finished recording, press the "stop" button. Don't worry about making mistakes or there being pregnant pauses because we can easily edit these out in the next step. When you have finished, the recording is displayed: Audacity is loaded with many great audio editing features, so by way of an example, I'm going to pick just one: Fade Out. Use the selection tool to select the final segment of your recording: From the main menu, select Effect | Fade Out. Try experimenting with some of the other audio options that are available: When you are happy with your recording, you'll need to save it. From the main menu, select File | Export as MP3…. Choose a suitable filename and location and click on the Save button. Complete the ID3 Tag dialog: Hit the OK button and Audacity creates your new MP3 file. That's it. We're done! Recording a narration—recap When my PowerPoint is included in my Moodle course, it will be viewed by students who won't have the benefit (or curse) of my commentary when I am giving my face-to-face teaching. It would be great if we could also include an audio commentary so that students can follow the presentation in their own time, at their own pace. To that end we've just used the free audio recording and editing tool, Audacity, to create an audio commentary for our PowerPoint presentation.
Read more
  • 0
  • 0
  • 2259

article-image-working-forms-dynamics-ax-part-3
Packt
06 Jan 2010
9 min read
Save for later

Working with Forms in Dynamics AX: Part 3

Packt
06 Jan 2010
9 min read
Building checklists Anyone who preformed Dynamics AX application installation or upgrade has to be familiar with standard checklists. Normally, a checklist is a list of menu items displayed in logical sequence. Each item represents either mandatory or optional actions to be executed by the user in order to complete the whole procedure. In custom Dynamics AX implementations, checklists can be used as a convenient way to configure non standard settings. Checklists can also be implemented as a part of third-party modules for their initial setup. In this recipe, we will create a checklist for user-friendly ledger budget setup. The checklist will consists of two mandatory and one optional item. How to do it... Open AOT, and create a new class called SysCheckListInterfaceBudget: interface SysCheckListInterfaceBudgetextends SysCheckListInterface{} Create three more classes—one for each checklist item, with the following code: class SysCheckListItem_BudgetModelextends SysCheckListItemimplements SysCheckListInterfaceBudget{}public str getCheckListGroup(){ return "Setup";}public str getHelpLink(){ #define.TopicId('AxShared.chm::/html/' + '84030522-0057-412C-BFC7-DBEB4D40E5A1.htm') ; return SysCheckListItem::sharedGuide(#TopicId);}public MenuItemName getMenuItemName(){ return menuitemdisplaystr(BudgetModel);}public MenuItemType getMenuItemType(){ return MenuItemType::Display;}str label(){ return "Models";}class SysCheckListItem_BudgetRevisionextends SysCheckListItemimplements SysCheckListInterfaceBudget{}public void new(){; super(); this.placeAfter(classnum(SysCheckListItem_BudgetModel)); this.indeterminate(true);}public str getCheckListGroup(){ return "Setup";}public str getHelpLink(){ #define.TopicId('AxShared.chm::/html/' + 'AACC4353-C3EB-4982-BB7F-2B36D97FF25B.htm') ; return SysCheckListItem::sharedGuide(#TopicId);}public MenuItemName getMenuItemName(){ return menuitemdisplaystr(BudgetRevision);}public MenuItemType getMenuItemType(){ return MenuItemType::Display;}str label(){ return "Revisions";}class SysCheckListItem_Budgetextends SysCheckListItemimplements SysCheckListInterfaceBudget{}public void new(){; super(); this.addDependency( classnum(SysCheckListItem_BudgetModel)); this.placeAfter( classnum(SysCheckListItem_BudgetRevision));}public str getCheckListGroup(){ return "Create budgets";}public str getHelpLink(){ #define.TopicId('AxShared.chm::/html/' + '6A596E1E-6803-4410-B4E4-EDE4EF44AF6D.htm') ; return SysCheckListItem::sharedGuide(#TopicId);}public MenuItemName getMenuItemName(){ return menuitemdisplaystr(LedgerBudget);}public MenuItemType getMenuItemType(){ return MenuItemType::Display;}str label(){ return "Budgets";} Create another class for the checklist itself: class SysCheckList_Budget extends SysCheckList{ container log;}protected str getCheckListCaption(){ return "Budget checklist";}protected str getHtmlHeader(){ return "Budget checklist";}protected classId getInterfaceId(){ return classnum(SysCheckListInterfaceBudget);}public void save( identifiername _name, ClassDescription _description){; if (!confind(log, _name)) { log = conins(log, conlen(log)+1, _name); }}public boolean find( identifiername _name, ClassDescription _description){ return confind(log, _name) ? true : false;}static void main(Args _args){; SysCheckList::runCheckListSpecific( classnum(SysCheckList_Budget), true);} Open the SysCheckList class in AOT, and replace its checkListItemsHook() and checkListsHook() with the following code: protected static container checkListsHook(){ return [classnum(SysCheckList_Budget)];}protected static container checkListItemsHook(){ return [classnum(SysCheckListItem_Budget), classnum(SysCheckListItem_BudgetRevision), classnum(SysCheckListItem_BudgetModel)];} Open the BudgetModel form in AOT, and override its close() with the following code: public void close(){; super(); SysCheckList::finished( classnum(SysCheckListItem_BudgetModel));} Open the BudgetRevision form in AOT, and override its close() with the following code: public void close(){; super(); SysCheckList::finished( classnum(SysCheckListItem_BudgetRevision));} Open the LedgerBudget form in AOT, and override its close() with the following code: public void close(){; super(); SysCheckList::finished(classnum(SysCheckListItem_Budget));} Create a new Display menu item SysCheckList_Budget with the following properties: Property Value Name SysCheckList_Budget Label Budget checklist ObjectType Class Object SysCheckList_Budget To test the checklist, run the SysCheckList_Budget menu item from AOT. The following should appear on the right-hand side of the Dynamics AX window: Click on the listed items to start and complete relevant actions. Notice how the status icons change upon completion of each task. How it works... The main principle behind checklists is that we have to create a main class, which represents the checklist itself and a number of SysCheckListItem item classes, which act as list items. The relation between the main class and the items is made by the use of an interface, that is, each list item implements it, and the main class holds the reference to it. In this example, we create an interface SysCheckListInterfaceBudget and specify it in the getInterfaceId() of the main checklist class SysCheckList_Budget. Next, we implement the interface in three SysCheckListItem classes, which correspond to Models, Revisions, and Budgets items in the checklist. Each SysCheckListItem class contains a set of inherited methods, which allows us to define a number of different parameters for individual items: All initialization code can be added to the new() methods. In this example, we use placeAfter() to determine the position of the item in the list relative to other items, indeterminate() to make item optional and addDependency() to make an item inactive until another specified item is completed. getCheckListGroup() defines item dependency to a specific group. The Budget checklist has two groups, Setup and Create budgets. getHelpLink() is responsible for placing the relevant help link in the form of a question mark next to the item. getMenuItemName() and getMenuItemType() contain a name and a type of menu item, which is executed upon user request. Here, we have Budget model, Budget revisions, and Ledger budget forms respectively in each class. And finally custom labels can be set in label(). Once the items are ready, we create the main checklist class SysCheckList_Budget, which extends the standard SysCheckList. We override some of the methods to add custom functionality to the checklist: getCheckListCaption() sets the title of the checklist. getHtmlHeader() could be used to add some descriptive text. As mentioned before, getInterfaceId() is the place where we specify the name of the checklist item interface. The methods save() and find() are used to store and retrieve respectively the status of each item in the list. In this example, we store statuses in the local variable log to make sure that statuses are reset every time we run the checklist. The static method main() runs the class. Here, we use runCheckListSpecific() of the system SysCheckList class to start the checklist. The display menu item we created is pointing to the checklist class and may be used to add the checklist to a user menu. When building checklists, it is necessary to add them and their items to the global checklist and checklist item list. The SysCheckList class contains two methods—checkLists() and checkListItems()—where all system checklists and their items are registered. The same class provides two more methods—checkListsHook() and checkListItemsHook()—where custom checklists should be added. As a part of this example, we also add our budget checklist and its items to the SysCheckList. Final modifications have to be done in all checklist forms. We call the finished() of the SysCheckList class in the close() of each form to update the status of the corresponding checklist item. In other words, it means that item status will be set as completed when the user closes the form. This code does not affect the normal use of the form when it is opened from the regular menu. Of course, more logic could be added here if the completion of a specific item is not that straightforward. Also notice that the system automatically adds a link called Information, which describes the checklist statuses: There's more... The checklist in this example stores item statuses per each run. This means that every time you close the checklist, its statuses are lost and are set to their initial states upon checklist start. By replacing save() and find() in SysCheckList_Budget with the following code, we can store statuses permanently in the SysSetupLog table: public boolean find( identifiername _name, ClassDescription _description){ return SysSetupLog::find(_name, _description).RecId != 0;}public void save( identifiername _name, ClassDescription _description){; SysSetupLog::save(_name, _description);} In this case, every time the checklist starts, the system will pick up its last status from the SysSetupLog table and allow the user to continue the checklist. Adding a "Go to the Main Table Form" link Go to the Main Table Form is a feature of Dynamics AX, which allows users to jump to the main record just by right-clicking on the field and selecting the Go to the Main Table Form option. It is based on table relations and is available for those controls whose data fields have foreign key relationships with other tables. Because of the data structure integrity, this feature works most of the time. However, when it comes to complex table relations, it does not work correctly or does not work at all. Another example of when this feature does not work automatically is when the form control is not bound to a table field. In such situations, Go to the Main Table Form has to be implemented manually. In this recipe, to demonstrate how it works, we will modify the Business relations form in the CRM module to make sure that the Employee filter at the top of the form allows users to use the Go to the Main Table Form feature from the context menu. How to do it... Open the smmBusRelTable form in AOT, and override jumpRef() of the EmployeeFilter control with: public void jumpRef(){ EmplTable emplTable; Args args; MenuFunction menuFunction; ; emplTable = EmplTable::find(this.text()); if (!emplTable) { return; } args = new Args(); args.caller(element); args.record(emplTable); menuFunction = new MenuFunction( menuitemdisplaystr(EmplTable), MenuItemType::Display); menuFunction.run(args);} To test the result, open CRM | Business Relation Details, make sure an employee number is specified in the Employee filter, and right-click on the filter control. Notice that the Go to the Main Table Form option, which will open the Employee form, is now available: How it works... Normally, the Go to the Main Table Form feature is controlled by the relations between tables. If there are no relations or the form control is not bound to a table field, then this option is not available. But, we can force this option to appear by overriding the control's jumpRef() method. In this method, we have to add code that opens the relevant form. This can be done by creating, initializing, and running a FormRun object, but the easier way is to simply run the relevant menu item. In this recipe, the code in jumpRef() does exactly that. First, we check if the value in the control is a valid employee number. If yes, then we run the Display menu item EmplTable with an Args object containing the proper employee record. The rest is done automatically by the system, that is, the Employee form is opened with the employee information.
Read more
  • 0
  • 0
  • 2857

article-image-enhancing-your-math-teaching-using-moodle-19-part-2
Packt
06 Jan 2010
4 min read
Save for later

Enhancing Your Math Teaching using Moodle 1.9: Part 2

Packt
06 Jan 2010
4 min read
Uploading to SlideShare Navigate your browser to http://slideshare.net. You'll need a SlideShare account. Once you've logged in you'll be able to upload your presentation: Select My Slidespace from the menu at the top of the page: Click on the Upload your first slideshow now link: Use the Upload page to choose your presentation and upload it to SlideShare: Once the file is uploaded, you can specify how it can be shared. Note that you can choose to make the presentation private (you don't have to make it available to the entire world): When you are done with the details, click on the Publish button. The presentation needs to be converted so that SlideShare can display it correctly. This can take a while, but you can check the status to see how SlideShare is getting on: Once the presentation has been converted, it's ready to view: That's it! The presentation is online and ready to go. Here are just a few of the advantages of using SlideShare to include your presentation in a Moodle course: Your students may not have PowerPoint installed on their computers nor be aware of the special player they can download (check out the Microsoft website for details). That's no problem! SlideShare will play the presentation for them. You don't have to worry about file sizes. The presentation is stored on SlideShare's computers and not in your Moodle. Using SlideShare's built-in tools, it's easy to create an audio commentary (more on this in the next section). But there can be disadvantages. For example, I tried making my presentation more engaging and entertaining by including animations (which is good if you are a visual/spatial learner). However, in SlideShare those animations no longer work. So, how do you actually include a SlideShare presentation in a Moodle course? Let's do this now: SlideShare provides a fragment of web page code along with each presentation: Right-click on the code, and choose Select All followed by Copy. In your Moodle course, you can include the slideshow using the HTML editor. I'm going to include the presentation on a Moodle web page. Click on the Toggle HTML Source button: Cursor to the end of the page's HTML code, right-click and select Paste: Click on the Toggle HTML Source button again and the slideshow gets displayed in the editor: It's that simple! Look for embedded code in your favorite content sharing websites (for example, YouTube). Audio commentaries and SlideShare—slidecasts We've already seen how we can record an audio commentary using Audacity. I've mentioned that you can create an audio commentary (or slidecast) using SlideShare. Let's do that now. I can use the recording I made previously to narrate the presentation uploaded to SlideShare: Return to your my slidespace area. Click on the Edit link under your presentation: On the Edit Slideshow Details page, click on the Create Slidecast tab: The Create Slidecast page is displayed. As the instructions on this page recommend, you will need to upload your commentary to the Internet. You won't be able to use Moodle, as your course files area isn't accessible outside of Moodle (that's one of Moodle's vital security features). I'm going to upload my narration to the Internet Archives You'll need a registered account to do this. Simply follow the instructions to upload your file: Copy the link to the audio file to the Create Slidecast page (if you are using the Internet Archive, then the individual audio files are listed at the bottom of the archive page). Click on the Link mp3 to slideshow button: Once the audio is processed, the Synchronization Tool is displayed. Use the tool to associate a slide with the correct fragment of audio: Once you are happy with your new slidecast, click on the Save & Publish button in the bottom-right corner of the page: Return to your My Slidespace page. Click on your presentation. You will now see a note in the corner of the presentation: That's it. We're done! Before we leave our discussion of SlideShare, make a note of the SlideShare sidebar. If you've more than one presentation in your course, it can make finding the right presentation easier for your students. Visit http://www.slideshare.net/widgets/blogbadge for more details.
Read more
  • 0
  • 0
  • 1506

article-image-funambol-development
Packt
06 Jan 2010
8 min read
Save for later

Funambol development

Packt
06 Jan 2010
8 min read
Data synchronization All mobile devices—handheld computers, mobile phones, pagers, and laptops—need to synchronize their data with the server where the information is stored. This ability to access and update information on the fly is the key to the pervasive nature of mobile computing. Yet, today almost every device uses a different technology for data synchronization. Data synchronization is helpful for: Propagating updates between a growing number of applications Overcoming the limitations of mobile devices and wireless connections Maximizing the user experience by minimizing data access latency Keeping scalability of the infrastructure in an environment where the number of devices (clients) and connections tend to increase considerably Understanding the requirements of mobile applications, providing a user experience that is helpful, and not an obstacle, for mobile tasks Data synchronization is the process of making two sets of data look identical, as shown in the following figure: This involves many techniques, which will be discussed in the following sections. The most important are: ID handling Change detection Modification exchange Conflict detection Conflict resolution Slow and fast synchronization ID handling At first glance, ID handling seems like a pretty straightforward process that requires little or no attention. However, ID handling is an important aspect of the synchronization process and is not trivial. In some cases a piece of data is identifiable by a subset of its content fields. For example, in the case of a contact entry, the concatenation of a first name and last name uniquely selects an entry in the directory. In other cases, the ID is represented by a particular field specifically introduced for that purpose. For example, in a Sales Force Automation mobile application, an order is identified by an order number or ID. The way in which an item ID is generated is not predetermined and it may be application or even device specific. In an enterprise system, data is stored in a centralized database, which is shared by many users. Each single item is recognized by the system because of a unique global ID. In some cases, two sets of data (the order on a client and the order on a server) represent the same information (the order made by the customer) but they differ. What could be done to reconcile client and server IDs to make the information consistent? Many approaches can be chosen: Client and server agree on an ID scheme (a convention on how to generate IDs must be defined and used). Each client generates globally unique IDs (GUIDs) and the server accepts client-generated IDs. The server generates GUIDs and each client accepts those IDs. Client and server generate their own IDs and a mapping is kept between the two. Client-side IDs are called Locally Unique Identifiers (LUID) and server-side IDs are called Globally Unique Identifiers (GUID). The mapping between local and global identifiers is referred as LUID-GUID mapping. The SyncML specifications prescribe the use of LUID-GUID mapping technique, which allows maximum freedom to client implementations. Change detection Change detection is the process of identifying the data that was modified after a particular point in time that is, the last synchronization. This is usually achieved by using additional information such as timestamp and state information. For example, a possible database enabled for efficient change detection is shown in the following table: ID First name Last name Telephone State Last_update 12 John Doe +1 650 5050403 N 2008-04-02 13:22 13 Mike Smith +1 469 4322045 D 2008-04-01 17:32 14 Vincent Brown +1 329 2662203 U 2008-03-21 17:29 However, sometimes legacy databases do not provide the information needed to accomplish efficient change detection. As a result, the matter becomes more complicated and alternative methods must be adopted (based on content comparison, for instance). This is one of the most important aspects to consider when writing a Funambol extension, because the synchronization engine needs to know what's changed from a point in time. Modification exchange A key component of a data synchronization infrastructure is the way modifications are exchanged between client and server. This involves the definition of a synchronization protocol that client and server use to initiate and execute a synchronization session. In addition to the exchange modification method, a synchronization protocol must also define a set of supported modification commands. The minimal set of modification commands are as follows: Add Replace Delete Conflict detection Let's assume that two users synchronize their local contacts database with a central server in the morning before going to the office. After synchronization, the contacts on their smartphones are exactly the same. Let's now assume that they update the telephone number for "John Doe" entry and one of them makes a mistake and enters a different number. What will happen the next morning when they both synchronize again? Which of the two new versions of the "John Doe" record should be taken and stored into the server? This condition is called conflict and the server has the duty of identifying and resolving it. Funambol detects a conflict by means of a synchronization matrix shown in the following table: Database A → ↓ Database B New Deleted Updated Synchronized / Unchanged Not Existing New C C C C B Deleted C X C D X Updated C C C B B Synchronized/Unchanged C D A = B Not Existing A X A A X As both users synchronize with the central database, we can consider what happens between the server database and one of the client databases at a time. Let's call Database A, as the client database and Database B, as the server database. The symbols in the synchronization matrix have the following meaning: X: Do nothing A: Item A replaces item B B: Item B replaces item A C: Conflict D: Delete the item from the source(s) containing it Conflict resolution Once a conflict arises and is detected, proper action must be taken. Different policies can be applied. Let's see some of them: User decides: The user is notified of the conflict condition and decides what to do. Client wins: The server silently replaces conflicting items with the ones sent by the client. Server wins: The client has to replace conflicting items with the ones from the server. Timestamp based: The last modified (in time) item wins. Last/first in wins: The last/first arrived item wins. Merge: Try to merge the changes, at least when there is no direct conflict. Consider the case of a vcard, where two concurrent modifications have been applied to two different fields. There is a conflict at the card level, but the two changes can be merged so that both clients can then have a valid version of the card. This is the best example of the case when the change is not directly conflicting. Do not resolve. Note that Funambol adopts a special merging policy that guarantees that the user does not lose data. The server always tries to merge if possible. When a conflict cannot be resolved with merging (for example, there are conflicting changes on the same field), the value in the last synchronization wins over the older synchronizations to meet the expectation of the user who is synchronizing. In this way, when the users who applied previous changes receive the new updates all devices will be in sync. Synchronization modes: Full or fast There are many modes to carry out the synchronization process. The main distinction is between fast and full synchronization. Fast synchronization involves only the items changed since the last synchronization between two devices. Of course, this is an optimized process that relies on the fact that, the devices were fully synchronized at some point in the past; this way, the state at the beginning of the sync operation is well known and sound. When this condition is not met (for instance, the mobile device has been reset and lost the timestamp of the last synchronization), a full synchronization must be performed. In a full synchronization, the client sends its entire database to the server, which compares it with its local database and returns the modifications that must be applied to be up-to-date again. Both fast and full synchronization modes can be performed in one of the following manners: Client-to-server: The server updates its database with client modifications, but sends no server-side modifications Server-to-client: The client updates its database with server modifications, but sends no client-side modifications Two-way: The client and server exchange their modifications and both databases are updated accordingly Extending Funambol The Funambol platform can be extended in many areas to integrate Funambol with existing systems and environments. The most common integration use cases and the Funambol modules involved are: Officer: Integrating with an external authentication and authorization service SyncSource: Integrating with an external datasource to address client specific issues Synclet: Adding pre or postprocessing to a SyncML message Admin WS: Integrating with an external management tool These are illustrated in the following diagram: Funambol extensions are distributed and deployed as Funambol modules. This section describes the structure of a Funambol module, while the following sections describe each of these listed scenarios. A Funambol module represents the means by which developers can extend the Funambol server. A module is a packaged set of files containing Java classes, installation scripts, configuration files, initialization SQL scripts, components, and so on, used by the installation procedure to embed extensions into the server core. For more information on how to install Funambol modules, see the Funambol Installation and Administration Guide.
Read more
  • 0
  • 0
  • 1863

article-image-getting-your-hands-dirty-jpdl-part-1
Packt
06 Jan 2010
9 min read
Save for later

Getting Your Hands Dirty with jPDL: Part 1

Packt
06 Jan 2010
9 min read
This example will introduce us to all the basic jPDL nodes used in common situations for modeling real world scenarios. That's why this article will cover the following topics: Introduction to the recruiting example Analyzing the example requirements Modeling a formal description Adding technical details to our formal description Running our processes The idea of this article is to show you a real process implementation. We will try to cover every technical aspect involved in development in order to clarify not only your doubts about modeling, but also about the framework behavior. How is this example structured? In this article, we will see a real case where a company has some requirements to improve an already existing, but not automated process. The current process is being handled without a software solution, practically we need to see how the process works everyday to find out the requirements for our implementation. The textual/oral description of the process will be our first input, and we will use it to discover and formalize our business process definition. Once we have a clear view about the situation that we are modeling, we will draw the process using GPD, and analyze the most important points of the modeling phase. Once we have a valid jPDL process artifact, we will need to analyze what steps are required for the process to be able to run in an execution environment. So, we will add all the technical details in order to allow our process to run. At last, we will see how the process behaves at runtime, how we can improve the described process, how we can adapt the current process to future changes, and so on. Key points that you need to remember In these kind of examples, you need to be focused on the translation that occurs from the business domain to the technical domain. You need to carefully analyze how the business requirements are transformed to a formal model description that can be optimized. Another key point here, is how this formal description of our business scenario needs to be configured (by adding technical details) in order to run and guide the organization throughout its processes. I also want you to focus on the semantics of each node used to model our process. If you don't know the exact meaning of the provided nodes, you will probably end up describing your scenario with the wrong words. You also need to be able to distinguish between a business analyst model, which doesn't know about the jPDL language semantics and a formal jPDL process definition. At the same time, you have to be able to do the translations needed between these two worlds. If you have business analysts trained in jPDL, you will not have to do these kind of translations and your life will be easier. Understanding the nodes' semantics will help you to teach the business analysts the correct meaning of jPDL processes. Analyzing business requirements Here we will describe the requirements that need to be covered by the recruiting team inside an IT company. These requirements will be the first input to be analyzed in order to discover the business process behind them. These requirements are expressed in a natural language, just plain English. We will get these requirements by talking to our clients—in this case, we will talk to the manager of an IT company called MyIT Inc. in order to find out what is going on in the recruiting process of the company. In most cases, this will be a business analyst's job, but you need to be aware of the different situations that the business scenario can present as a developer. This is very important, because if you don't understand how the real situation is sub-divided into different behavioral patterns, you will not be able to find the best way to model it. You will also start to see how iterative this approach is. This means that you will first view a big picture about what is going on in the company, and then in order to formalize this business knowledge, you will start adding details to represent the real situation in an accurate way. Business requirements In this section, we will see a transcription about our talk with the MyIT Inc. manager. However, we first need to know the company's background and, specifically, how it is currently working. Just a few details to understand the context of our talk with the company manager would be sufficient. The recruiting department of the MyIT Inc. is currently managed without any information system. They just use some simple forms that the candidates will have to fill in at different stages during the interviews. They don't have the recruiting process formalized in any way, just an abstract description in their heads about how and what tasks they need to complete in order to hire a new employee when needed. In this case, the MyIT Inc. manager tells us the following functional requirements about the recruiting process that is currently used in the company: We have a lot of demanding projects, that's why we need to hire new employees on a regular basis. We already have a common way to handle these requests detected by project leaders who need to incorporate new members into their teams. When a project leader notices that he needs a new team member, he/she will generate a request to the human resources department of the company. In this request, he/she will specify the main characteristics needed by the new team member and the job position description. When someone in the human resources team sees the request, they will start looking for candidates to fulfill the request. This team has two ways of looking for new candidates: By publishing the job position request in IT magazines By searching the resume database that is available to the company When a possible candidate is found through these methods, a set of interviews will begin. The interviews are divided into four stages that the candidate needs to go through in order to be hired. These stages will contain the following activities that need to be performed in the prescribed order: Initial interview: The human resources team coordinates an initial interview with each possible candidate found. In this interview, a basic questionnaire about the candidate's previous jobs and some personal data is collected. Technical interview: During the technical interview stage, each candidate is evaluated only with the technical aspects required for this particular project. That is why a project member will conduct this interview. Medical checkups: Some physical and psychological examinations need to be done in order to know that the candidate is healthy and capable to do the required job. This stage will include multiple checkups which the company needs to determine if the candidate is apt for the required task. Final acceptance: In this last phase the candidate will meet the project manager. The project manager is in charge of the final resolution. He will decide if the candidate is the correct one for that job position. If the outcome of this interview is successful, the candidate is hired and all the information needed for that candidate to start working is created. If a candidate reaches the last phase and is successfully accepted, we need to inform the recruiting team that all the other candidate's interviews need to be aborted, because the job position is already fulfilled. At this point, we need to analyze and evaluate the manager's requirements and find a graphical way to express these stages in order to hire a new employee. Our first approach needs to be simple and we need to validate it with the MyIT Inc. manager. Let's see the first draft of our process: With this image, we were able to describe the recruiting process. This is our first approach that obviously can be validated with the MyIT Inc. manager. This is our first draft that tells us how our process will appear and it's the first step in order to define which activities will be included in our model and which will not. In real implementations, these graphs can be made with Microsoft Visio, DIA (Open Source project), or just by hand. The main idea of the first approach is to first have a description that can be validated and understood by every MyIT Inc. employee. This image is only a translation of the requirements that we hear from the manager using common sense and trying to represent how the situation looks in real life. In this case, we can say that the manager of the MyIT Inc. can be considered as the stakeholder and the Subject Matter Expert (SME), who know how things happen inside the company. Once the graph is validated and understood by the stakeholder, we can use our formal language jPDL to create a formal model about this discovered process. The idea at this point, is to create a jPDL process definition and discard the old graph. From now on we will continue with the jPDL graphic representation of the process. Here you can explain to the manager that all the new changes that affect your process will go directly to the jPDL defined process. Until now our artifact has suffered the following transformations: The final artifact (the jPDL process definition) will let us begin the implementation of all the technical details needed by the process in order to run in an execution environment. So, let's analyze how the jPDL representation will look for this first approach in the following figure: At this point we don't add any technical details, we just draw the process. One key point to bear in mind in this phase is that we need to understand which node we will use to represent each activity in our process definition. Remember that each node provided by jPDL has its own semantics and meanings. You also need to remember that this graph needs to be understood by the manager, so you will use it in the activity name business language. For this first approach we use state nodes to represent that each activity will happen outside the process execution. In other words, we need to inform the process when each activity ends. This will mean that the next activity in the chain will be executed. From the process perspective, it only needs to wait until the human beings in the company do their tasks.
Read more
  • 0
  • 0
  • 1894
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-getting-your-hands-dirty-jpdl-part-2
Packt
06 Jan 2010
4 min read
Save for later

Getting Your Hands Dirty with jPDL: Part 2

Packt
06 Jan 2010
4 min read
Describing how the job position is requested In the first part, we find all the answers to our questions; however, a few remain unanswered: How is the first part of the process represented? How can we track when the new job position is discovered, the request for that job position is created, and when this job position is fulfilled? Why can't we add more activities to the current defined process? What happens when we add the create request, find a candidate, and job position fulfilled activities inside the interview process? The answers for these questions are simple. We cannot add these proposed nodes to the same process definition, because the interview process needs to be carried out (needs to be instantiated) once for each candidate that the recruiting team finds. Basically, we need to decouple all these activities into two processes. As the MyIT Inc. manager said, the relationship between these activities is that a job request will be associated with the N-interviews' process. The other important thing to understand here, is that both the processes can be decoupled without using a parent/child relationship. In this case, we need to create a new interview's process instance when a new candidate is found. In other words, we don't know how many interviews' process instances are created when the request is created. Therefore, we need to be able to make these creations dynamically. We will introduce a new process that will define these new activities. We need to have a separate concept that will create an on-demand new candidate interviews' process, based on the number of candidates found by the human resources team. This new process will be called "Request Job Position" and will include the following activities: Create job request: Different project leaders can create different job requests based on their needs. Each time that a project leader needs to hire a new employee, a new instance of this process will be created where the first activity of this process is the creation of the request. Finding a candidate: This activity will cover the phase when the research starts. Each time the human resources team finds a new candidate inside this activity, they will create a new instance of the candidate interviews' process. When an instance of the candidate interviews' process finds a candidate who fulfills all the requirements for that job position, all the remaining interviews need to be aborted. We can see the two process relationships in the following figure: If we express the Request Job Position process in jPDL, we will obtain something like this: In the following section, we will see two different environments in which we can run our process. We need to understand the differences between them in order to be able to know how the process will behave in the runtime stage. Environment possibilities Based on the way we choose to embed the framework in our application, it's the configuration that we need. We have three main possibilities: Standalone applications Web applications Enterprise application Standalone application with jBPM embedded In Java Standard Edition (J2SE) applications, we can embed jBPM and connect it directly to a database in order to store our processes. This scenario will look like the following image: In this case, we need to include the jBPMJARs in our application classpath in order to work. This is because our application will use the jBPM directly in our classes. In this scenario, the end users will interact with a desktop application that includes the jbpm-jpdl.jar file. This will also mean that in the development process, the developers will need to know the jBPM APIs in order to interact with different business processes. It's important for you to know that the configuration files, such as hibernate.cfg.xml and jbpm.cfg.xml will be configured to access the database with a direct JDBC connection. Web application with jBPM dependency This option varies, depending on whether your application will run on an application server or just inside a servlet container. This scenario will look like: In this case, we can choose whether our application will include the jBPMJARs inside it, or whether the container will have these libraries. But once again, our application will use the jBPM APIs directly. In this scenario, the end user will interact with the process using a web page that will be configured to access a database by using a JDBC driver directly or between a DataSource configuration.
Read more
  • 0
  • 0
  • 1528

article-image-funambol-e-mail-part-2
Packt
06 Jan 2010
3 min read
Save for later

Funambol E-mail: Part 2

Packt
06 Jan 2010
3 min read
Mobile e-mail at work One of the most widely used phones for mobile e-mail are phones running Windows Mobile; therefore, this is a platform Maria will have to support. Funambol fully supports this platform, extending the Windows Mobile native e-mail client to support SyncML and Funambol mobile e-mail. As Windows Mobile does not natively support SyncML, Maria needs to download the Funambol Windows Mobile Sync Client from the following URLs: http://www.funambol.com/opensource/download.php?file_id=funambol-smartphone-sync-client-7.2.2.exe&_=d (for Windows Mobile smartphone) http://www.funambol.com/opensource/download.php?file_id=funambol-pocketpc-sync-client-7.2.2.exe&_=d (for Windows Mobile Pocket PC) Like any other Windows Mobile applications, these are executable files that need to be run on a desktop PC and the installation will be performed by Microsoft ActiveSync. Once installed on the mobile phone, Maria can run Funambol by clicking the Funambol icon. The first time the application is launched, it asks for the Funambol credentials, as shown in the following image: Maria fills in her Funambol Server location and credentials (not her e-mail account credentials) and presses Save. After a short while, the device will start downloading the messages that she can access from the Funambol account created by the Funambol installation program in Pocket Outlook. The inbox will look similar to the following image: To see mobile e-mail at work, Maria just needs to send an e-mail to the e-mail account she set up earlier. In less than a minute, her mobile device will be notified that there are new messages and the synchronization will automatically start (unless the client is configured differently). Mobile e-mail client configuration There are a number of settings that Maria can set on her mobile phone to change how mobile e-mail works. These settings are accessible from the Funambol application by clicking on Menu | Settings. There are two groups of settings that are important for mobile e-mail: E-mail options... and Sync Method. From the Email options panel, Maria can choose which e-mails to download (all e-mails, today's e-mails, or e-mails received from the last X days), the size of the e-mail to download first (then the remaining part can be downloaded on demand), and if she also wants to download attachments. In the advanced options, she can also choose to use a different "From" display name and e-mail address. From the push method panel, Maria can choose how to download e-mail automatically using the push service on a regular basis, with either a scheduled sync or only manually upon request (from the Funambol Windows Mobile Sync Client interface or the PocketOutlook send and receive command). Funambol supports many mobile phones for mobile e-mail. The previous description is only for Windows Mobile phones. The manner in which Funambol supports other devices depends on the phone. In some cases, Funambol uses the phone's native e-mail client, such as with Windows Mobile. In other cases, Funambol provides its own mobile e-mail client that is downloaded onto the device.
Read more
  • 0
  • 0
  • 2012

article-image-working-forms-dynamics-ax-part-2
Packt
06 Jan 2010
13 min read
Save for later

Working with Forms in Dynamics AX: Part 2

Packt
06 Jan 2010
13 min read
Adding form splitters Commonly used forms like Sales orders or Projects in Dynamics AX have multiple grids. Normally, one grid is in the upper section and another one is in the bottom section of the form. Sometimes grids are placed next to each other. The size of the data in each grid may vary, and that's why most of the forms with multiple grids have splitters in the middle so users can resize both grids at once by dragging the splitter with the help of a mouse. It is a good practice to add splitters to newly created forms. Although Microsoft developers did a good job by adding splitters to most of the multi-grid forms, there is still at least one that has not got it. It is the Account reconciliation form in the Bank module, which is one of the most commonly used forms. It can be opened from Bank | Bank Account Details, Functions | Account reconciliation button, and then the Transactions button. In the following screenshot, you can see that the size of the bottom grid cannot be changed: In this recipe, we will demonstrate the usage of splitters by resolving this situation. We will add a form splitter in the middle of the two grids in the mentioned form. It will allow users to define the sizes of both grids to make sure that the data is displayed optimally. How to do it... Open the BankReconciliation form in AOT, and create a new Group at the very top of the form's design with the following properties:   Property Value Name Top AutoDeclaration Yes FrameType None Width Column width   Move the AllReconciled, Balances, and Tab controls into the newly created group. Create a new Group right below the Top group with properties: Property Value Name Splitter AutoDeclaration Yes Width Column width Height 5 FrameType Raised 3D BackgroundColor Window background HideIfEmpty No AlignChild No Add the following line of code to the bottom of the form's class declaration: SysFormSplitter_Y fs; Add the following line of code to the bottom of the form's init(): fs = new SysFormSplitter_Y(Splitter, Top, element); Override three methods in the Splitter group with the following code: public int mouseDown( int _x, int _y, int _button, boolean _ctrl, boolean _shift) { return fs.mouseDown(_x, _y, _button, _ctrl, _shift); } public int mouseMove( int _x, int _y, int _button, boolean _ctrl, boolean _shift) { return fs.mouseMove(_x, _y, _button, _ctrl, _shift); } public int mouseUp( int _x, int _y, int _button, boolean _ctrl, boolean _shift) { return fs.mouseUp(_x, _y, _button, _ctrl, _shift); } Change the following properties of the existing BankTransTypeGroup group: Property Value Top Auto Width Column width Height Column height Change the following property of the exiting TypeSums grid located in BankTransTypeGroup group: Property Value Height Column height In AOT the Modified BankReconciliation form should look like the following screenshot: Now, to test the results, open Bank | Bank Account Details, select any bank account, click Functions | Account reconciliation, choose an existing or create a new account statement, and click the Transactions button. Notice that now the form has a nice splitter in the middle, which makes the form look better and allows defining the size of each grid: How it works... Normally a splitter is placed between two form groups. In this recipe, to follow that rule, we need to adjust the BankReconciliation form's design. The filter AllReconciled, the group Balances and the tab Tab are moved to a new group called Top. We do not want this new group to be visible to user, so we set FrameType to None. Setting AutoDeclaration to Yes allows us to access this object from X++ code. And finally, we make this group automatically expand in the horizontal direction by setting its Width to Column width. At this stage, visual form layout did not change, but now we have the upper group ready. The BankTransTypeGroup group could be used as a bottom group with slight changes. We change its Top behavior to Auto and make it fully expandable in the horizontal and vertical directions. The Height of the grid inside this group also has to be changed to Column height in order to fill all the vertical space. In the middle of those two groups, we add a splitter. The splitter is nothing else but another group, which looks like a splitter. In order to achieve that, we set Height to 5, FrameType to Raised 3D, and BackgroundColor to Windows background. This group does not hold any other controls inside. Therefore, in order to make it visible, we have to set the property HideIfEmpty to No. The value No of the property AlignChild makes the splitter begin on the very left side of the form and the Column width value of the property Width forces the splitter to automatically fill the form's width. Mouse events are handled by the SysFormSplitter_Y application class. After it has been declared in the form's class declaration, we create the actual object in the form's init(). We pass the name of the splitter control, the name of the top group and the form itself as arguments when creating it. A fully working splitter requires three mouse event handlers. It is implemented by overriding the mouseMove(), mouseDown(), and mouseUp() methods in the splitter group control. All arguments are passed to the respective member methods of the SysFormSplitter_Y class which does all the job. In this way, horizontal splitters can be easily added to any form. The Dynamics AX application also contains nice examples about splitters, which can be found in AOT in the Tutorial_Form_Split form. Vertical splitters can also be added to forms using a very similar approach. For this, we need to use another application class called SysFormSplitter_X. Creating modal forms During my trainings and working with Dynamics AX users, I noticed that people who are not familiar with computers and software tend to get lost among open application windows. The same could be applied to Dynamics AX. I experienced many times when a user opened one form, clicked some button to open another one, and then went back to the first one without closing the second one. Sometimes this happens intentionally, sometimes—not, but the result is that the second form is hidden behind the first one and the user starts wondering why it is not possible to close or edit the first form. Such issues could be easily solved by making the child form a modal window. In other words, the second form always stays on top of the fi rst one until closed. In this recipe, we will do exactly that. As an example, we will make the Create sales order form a modal window. How to do it... Open the SalesCreateOrder form in AOT, and set its Design property: Property Value WindowType Popup To test, open Accounts receivable | Sales Order Details, and start creating a new order. Notice that now the sales order creation form always stays on top of the Sales order form: How it works... Dynamics AX form design has a WindowType property, which is set to Standard by default. In order to make a form behave as a modal window, we have to change it to Popup. Such forms will always stay on top of the parent form. There's more... We already know that some of the Dynamics AX forms are created dynamically using the Dialog class. If we look deeper into the code, we could find that the Dialog class actually creates a runtime Dynamics AX form. That means we can apply the same principle, i.e. change the relevant form's design property. The following code could be added to the Dialog object and would do the job: dialog.dialogForm().buildDesign().windowType( FormWindowType::Popup); We get a reference to the form's design, by first using dialogForm() of the Dialog object to get a reference to the DialogForm object, and then we call buildDesign() on the latter object. Then, we set the design's property by calling its windowType() with an argument FormWindowType::Popup. Changing common form appearance In every single multi-company Dynamics AX project, in order to prevent user mistakes, I was asked to add functionality that allows setting the background color of every form per company. By doing that, users clearly see in which company account they are at the moment and can easily work within multiple companies at the same time. In this recipe, we will modify SysSetupFormRun class to change the background color for every form in Dynamics AX. How to do it... Open SysSetupFormRun in AOT, and override its run() with the following code: public void run() {; super(); this.design().colorScheme(FormColorScheme::RGB); this.design().backgroundColor(WinAPI::RGB2int(255,0,0)); } To test the results, open any Dynamics AX form, for example, General ledger | Chart of Accounts Details and notice how the background color is changed to red: How it works... SysSetupFormRun is the application class that is called by the system every time a user runs a form. The best place to add our custom code is to override the run() method and place it under the super(). We use this.design() to get a reference to the form's design. By calling colorScheme() and backgroundColor(), we set the color scheme to red/green/blue and the color code to red. We use WinAPI::RGB2int() to transform the human-readable red/green/blue code into the numeric color code. There's more... This recipe showed a very basic principle of how to change the common appearance of all forms with few lines of code. You noticed that the color in this recipe does not fi ll all areas of the form, which does not make the form look nice. An alternative to this could be to dynamically add a colored rectangle or something similar to the top of the form. The possibilities are endless here. New controls like input fields, buttons, menu items, and others could also be added to all forms dynamically using this class. But do not overdo as it may impact system performance. Storing last form values Dynamics AX has a very useful feature, which allows saving the latest user choices per user per form. This feature is implemented across a number of standard reports, periodic jobs, and other objects, which require user input. When developing a new functionality for Dynamics AX, I always try to keep that practice. One of the frequently used areas is custom filters for grid-based forms. Although, Dynamics AX allows users to use standard filtering for any grid, in practice sometimes it is not very useful, especially when the user requires something specific. In this recipe, we will see how to store the latest user filter selections. To make it as simple as possible, we will use existing filters on the General journal form, which can be opened from General ledger | Journals | General journal. This form contains two filters—Show and Show user-created only. Show allows displaying journals by their posting status and Show user-created only toggles between all journals and the currently logged user's journals. How to do it... Find the LedgerJournalTable form in AOT, and add the following code to the bottom of its class declaration: AllOpenPosted showStatus; NoYes showCurrentUser; #define.CurrentVersion(1) #localmacro.CurrentList showStatus, showCurrentUser #endmacro Create these additional form methods: public void initParmDefault() {; showStatus = AllOpenPosted::Open; showCurrentUser = true; } public container pack() { return [#CurrentVersion,#CurrentList]; } public boolean unpack(container packedClass) { int version = RunBase::getVersion(packedClass); ; switch (version) { case #CurrentVersion: [version,#CurrentList] = packedClass; return true; default: return false; } return false; } public identifiername lastValueDesignName() { return element.args().menuItemName(); } public identifiername lastValueElementName() { return this.name(); } public UtilElementType lastValueType() { return UtilElementType::Form; } public userId lastValueUserId() { return curuserid(); } public dataAreaId lastValueDataAreaId() { return curext(); } xSysLastValue::getLast(this); AllOpenPostedField.selection(showStatus); ShowUserCreatedOnly.value(showCurrentUser); journalFormTable.designSelectionChangeAllOpenPosted(); journalFormTable.designSelectionChangeShowUserCreateOnly(); And the following code to the bottom of the form's close(): showStatus = AllOpenPostedField.selection(); showCurrentUser = ShowUserCreatedOnly.value(); xSysLastValue::saveLast(this); Now to test the form, open General ledger | Journals | General journal, change filter values, close it, and run again. The latest filter selections should stay: How it works... First of all, we define some variables. We will store the journal posting status filter value in showStatus and the current user filter value in showCurrentUser. The macro #CurrentList is used to define a list of variables that we are going to store. Currently, we have two variables. The macro #CurrentVersion defines a version of saved values. In other words, it says that the variables defined by the #CurrentList, which will be stored in system cache later, can be addressed using the number 1. Normally, when implementing last value saving for the first time for particular object, #CurrentVersion is set to 1. Later on, if we decide to add new values or change existing ones, we have to change the value of #CurrentVersion, normally increasing it by 1. This ensures that the system addresses the correct list of variables in the cache and does not break existing functionality. The initParmDefault()method specifies default values if nothing is found in the system cache. Normally, this happens if we run a form for the first time, we change #CurrentVersion or clean the cache. Later, this method is called automatically by the xSysLastValue object. The methods pack() and unpack() are responsible for formatting a storage container from variables and extracting variables from a storage container respectively. In our case, pack() returns a container consisting of three values: version number, posting status, and current user toggle. Those values will be sent to the system cache after the form is closed. During an opening of the form, the xSysLastValue object uses unpack() to extract values from the stored container. It checks the container version from cache first, and if it matches the current version number, then the values from the cache are considered correct and are assigned to the form variables. A combination of lastValueDesignName(), lastValueElementName(), lastValueType(), and lastValueDataAreaId() return values form unique string representing saved values. This ensures that different users can store last values for different objects without overriding each other's values in cache. The lastValueDesignName() method is meant to return the name of the object's current design in cases where the object can have several designs. In this recipe, there is only one design, so instead of leaving it empty, I used it for a slightly different purpose. The same LedgerJournalTable AOT form can represent different user forms like Ledger journal, Periodic journal, Vendor payment journal, and so on depending on the location from which it was opened. To ensure that the user's latest choices are saved correctly, we included the opening menu item name as part of the unique string. The last two pieces of code need to be added to the bottom of the form's run() and close(). In the run() method, xSysLastValue::getLast(this) retrieves saved user values from cache and assigns them to the form's variables. The next two lines assign the same values to the respective form controls. designSelectionChangeAllOpenPosted() and designSelectionChangeShowUserCreateOnly() execute a form query to apply updated filters. Although both of those methods currently perform exactly the same action, we keep both for the future in case this functionality is updated. Code lines in close() are responsible for assigning user selections to variables and saving them to cache by calling xSysLastValue::saveLast(this).
Read more
  • 0
  • 0
  • 9116

article-image-funambol-e-mail-part-1
Packt
06 Jan 2010
6 min read
Save for later

Funambol E-mail: Part 1

Packt
06 Jan 2010
6 min read
In this article, Maria will set up Funambol to connect to the company e-mail server, in order to enable her users to receive e-mail on their mobile phones. E-mail Connector The E-mail Connector allows Funambol to connect to any IMAP and POP e-mail server to enable mobile devices to receive corporate or personal e-mail. The part of the Funambol architecture involved with this functionality is illustrated in the following figure: The E-mail Connector is a container of many things, the most important ones being: The e-mail server extension (represented in the figure by the E-mail Connector block): This is the extension of the Funambol Data Synchronization Service that allows e-mail synchronization through the connection to the e-mail provider. The Inbox Listener Service: This is the service that detects new e-mail in the user inbox and notifies the user's devices. When the Funambol DS Service receives sync requests for e-mail, the request calls the E-mail Connector, which downloads new messages from the e-mail server and makes them available to the DS Service, which in turn delivers them to the device. When a user receives a new e-mail, the new message is detected by the Inbox Listener Service that notifies the user's device to start a new sync. When the E-mail Connector is set up and activated, e-mail can be synced with an e-mail provider if it supports one of the two popular e-mail protocols—POP3 or IMAP v4 for incoming e-mail and the SMTP protocol for outgoing e-mail delivery. Please note that the Funambol server does not store user e-mail locally. For privacy and security reasons, e-mail is stored in the e-mail store of the E-mail Provider. The server constructs a snapshot of each user's inbox in the local database to speed up the process of discovering new e-mails without connecting to the e-mail server. Basically, this e-mail cache contains the ID of the messages and their received date and time. The Funambol service responsible for populating and updating the user inbox cache is the Inbox Listener Service. This service checks each user inbox on a regular basis (that is, every 15 minutes) and updates the inbox cache, adding new messages and deleting the messages that are removed from the inbox (for example, when a desktop client downloaded them or the user moved the messages to a different folder). Another important aspect to consider with mobile e-mail is that many devices have limited capabilities and resources. Further, the latency of retrieving a large inbox can be unacceptable for mobile users, who need the device to be always functional when they are away from their computer. For this reason, Funambol limits the maximum number of e-mails that Maria can download on her mobile so that she is never inconvenienced by having too many e-mails in her mobile e-mail inbox. This value can be customized in the server settings (see section E-mail account setup). In the following sections, Maria will learn how to set up Funambol to work with the corporate e-mail provider and how she can provide Funambol mobile e-mail for her users. Setting up Funambol mobile e-mail The Funambol E-mail Connector is part of a default installation of Funambol so Maria does not need to install any additional packages to use it. The following sections describe what Maria needs to do to set up Funambol to connect to her corporate e-mail server. E-mail Provider The only thing that Maria needs to make sure about the corporate E-mail Provider is that it supports POP/IMAP and SMTP access from the network where Funambol is installed. It is not necessary that the firewall is open to mobile devices. Devices will keep using SyncML as the transport protocol, while the Funambol server connects to the e-mail server when required. Also, the same e-mail server does not need to provide both POP (or IMAP) and SMTP. Funambol can be configured to use two different servers for incoming and outgoing messages. Funambol authentication with e-mail One of Maria's security concerns is the distribution and provisioning of e-mail account information on the mobile phones. She does not like the fact that e-mail account information is sent over a channel that she can only partially control. This is a common concern of IT administrators. Funambol addresses this issue by not storing e-mail credentials on the device. The device (or any other SyncML client) is provisioned with Funambol credentials. In the previous sections, Maria was able to create new accounts so that users could use the PIM synchronization service, and in doing so, she needed to provide new usernames and passwords. This is still valid for e-mail users. What Maria needs to do now is to configure the E-mail Connector and add the e-mail account of the users she wants to enable for mobile e-mail. These topics are covered in detail in the following sections. E-mail account setup To add a user e-mail account to the synchronization service, Maria can use the Funambol Administration Tool, expanding the Modules | email | FunambolEmailConnector node and double-clicking the connector. This opens the connector administration panel, as shown in the following screenshot: There are two sections: Public Mail Servers and Accounts. Maria needs to add new accounts. Let's start with her account first. Clicking the Add button in the Accounts section opens up a new search window so that she can search which Funambol user to attach to the e-mail account. Typing maria in the Username field and clicking Search, will show you the result as shown in the following screenshot: Double-clicking the desired account displays a form for maria's account details as shown in the following screenshot: Each field is explained as follows: Login, Password, Confirm password, and E-mail addressAs the labels of the fields describe, these are the e-mail account credentials and e-mail address. These are credentials used to access the e-mail service, not the ones to access the Funambol synchronization service. Enable PollingThis setting enables or disables the functionality of the Inbox Listener Service to check for updates on this account's inbox. When disabled, the account inbox won't be scanned for new/updated/deleted e-mail. This disables e-mail synchronization completely. Enable PushThis setting enables or disables the push functionality. When disabled, the user will not be notified of new e-mails. If Enable Polling checkbox is active, the Inbox Listener Service keeps updating this account's e-mail cache anyway. In this case Maria can still download e-mail by manually starting the synchronization from the client. Refresh time(min) This setting specifies how frequently the Inbox Listener Service checks for updates on this account's inbox. The value is expressed in minutes. The shorter this period, the more often new e-mail is detected and therefore the closer the user experience is to real time. However, the smaller this number, the heavier the load on the Inbox Listener Service and the e-mail provider. When you have only a few users, this is not too relevant, but it is something to consider when planning a major deployment.
Read more
  • 0
  • 0
  • 2416
article-image-networking-openvpn
Packt
05 Jan 2010
7 min read
Save for later

Networking with OpenVPN

Packt
05 Jan 2010
7 min read
The modular structure of OpenVPN can not only be found in its security model, but also in the networking scheme. James Yonan chose the Universal TUN/TAP driver for the networking layer of OpenVPN. The TUN/TAP driver is an open source project that is included in all modern Linux/Unix distributions, as well as Windows, Solaris, and Mac OS X. Like SSL/TLS, it is used in many projects, and therefore it is steadily being improved, and new features are being added. Using the TUN/TAP devices takes away a lot of complexity from the structure of OpenVPN. Its simple structure brings increased security when compared to other VPN solutions. Complexity is always the main enemy of security. For example, IPsec has a complex structure with complex modifications in the kernel and the IP stack, thereby creating many possible security loopholes. The Universal TUN/TAP driver was developed to provide Linux kernel support for tunneling IP traffic. It is a virtual network interface, which appears as authentic to all applications and users. Only the name tunX or tapX distinguishes it from other devices. Every application that is capable of using a network interface can use the tunnel interface. Every technology that you are running in your network can be run on a TUN or TAP interface too. This driver is one of the main factors that makes OpenVPN very easy to understand, easy to configure, and at the same time, very secure. The following figure depicts OpenVPN using standard interfaces: A TUN device can be used like a virtual point-to-point interface, like a modem or DSL link. This is called routed mode because routes are set up to the VPN partner. However, a TAP device can be used like a virtual Ethernet adapter. This enables the daemon listening on the interface to capture Ethernet frames, which is not possible with TUN devices. This mode is called bridging mode because the networks are connected as if over a hardware bridge. Applications can read/write to this interface. Software (the tunnel driver) will take all the data and use the cryptographic libraries of SSL/TLS to encrypt them. The data is packaged and sent to the other end of the tunnel. This packaging is done with standardized UDP or optional TCP packets. UDP should be the first choice, but TCP can be helpful in some cases. You are almost completely free to choose the configuration parameters such as protocol or port numbers, as long as both tunnel ends agree on the same figures. OpenVPN listens on TUN/TAP devices, takes the traffic, encrypts it, and sends it to the other VPN partner, where another OpenVPN process receives the data, decrypts it, and hands it over to the virtual network device, where the application might already be waiting for the data. As far as I know, there are only few other VPN software applications that enable VPN partners to transmit. This concept offers the following exciting possibilities: Broadcasts are needed for browsing Windows networks or for LAN games Non-IP packets like IPX be used and almost anything is possible in your LAN that is sent over the VPN to the other side As OpenVPN uses standard network packets, NAT is no problem either. A host in the local net in Sydney with a local IP can start a tunnel to another host in the local net in London, if it is also equipped with a local IP. But there's more. As the network interface is a standardized Linux network interface (either TUN or TAP), anything possible on an Ethernet NIC can also be done on VPN tunnels. Consider the following: Firewalls can restrict and control traffic Traffic shaping is not only possible, but it is also a feature incorporated in OpenVPN Also, if you want to use DSL lines with frequent reconnects and dynamically assigned IPs, OpenVPN will be your first choice. The reconnect is much faster than that of any other VPN software that we have tested. A Windows terminal server or SSH session does not terminate when one of the VPN partners changes its IP. The session just freezes for a few seconds and then you can continue. Can your VPN accomplish that? OpenVPN and firewalls OpenVPN works perfectly with firewalls. There are a few VPN solutions that can claim to have similar firewall support, but none can offer the same level of security. What is a firewall? There is a famous and simple definition. A firewall is a router that does not route. If you consider this to be not very helpful, then here is a more refined definition: A firewall is a router that routes only selected Internet data. Firewall rules define how to handle specific data and traffic. Firewalls can be devices or software on PCs, servers, or on other devices. A firewall takes care of the data that has been received and has a closer look at it. Modern firewalls are so-called packet filtering, stateful inspection firewalls. Depending on the OSI layer it is operating in, the firewall can pass decisions based on the data that is found in the headers of the packets or application data. Packet filtering firewalls usually operate by reading the IP data header. Stateful inspection is a mechanism to remember the connection states. In this way, internal networks can be protected from external networks. While Internet connections initiated from the inside can be allowed, all unwanted unauthorized connections from the outside can be rejected. At the same time, incoming data requested by a member of the local net is passed through (because the firewall remembers the state of the request). Under Linux, most firewalls are based on the program iptables. This is a user-space interface to the Linux kernel's netfilter firewall functionality, and offers everything that modern firewalls should. Probably the best way to protect your LAN is by writing a set of iptables rules with a shell script. However, the usability of such a script is not perfect. Most administrators want a Graphical User Interface (GUI) for firewall control and all the hardware firewalls offer this. Enterprise Distributions, such as RHEL or SLES come with sophisticated firewall tools, but there are also several open source projects. Outstanding tools for this purpose and Linux (iptables) firewalls are as follows: The Shorewall (Shoreline Firewall) project that integrates into the Webmin suite—a web-based frontend to administer Linux systems from a browser. People from the Shorewall project, namely, Simon Matter and Tom Eastep, have written a very useful guideline for the integration of OpenVPN tunnels into Shorewall and more at http://www.shorewall.net/OPENVPN.html. IPCop (http://www.ipcop.org) is a promising standalone, easy-to-configure Linux firewall system that is also equipped with a professional GUI. It has had great success in third-world projects like Linux4africa (http://www.linux4africa.de) and in other medium-size professional setups. Standardized installation, simple structures, and modular add-ons make this a fast-growing project, and with the help of OpenVPN, the IPCop firewall becomes a true VPN server. Tools like Fwbuilder (http://www.fwbuilder.org) help you build, manage, and distribute your iptables scripts on your own. Fwbuilder does even more. It can work independently from your platform and is able to translate Linux rules into Cisco, BSD, or other firewall languages. This is really worth a look.
Read more
  • 0
  • 0
  • 5479

article-image-building-form-applications-joomla-using-ck-forms
Packt
05 Jan 2010
4 min read
Save for later

Building Form Applications in Joomla! using CK Forms

Packt
05 Jan 2010
4 min read
(For more resources on Joomla!, see here.) Add a quick survey  form to your Joomla site Dynamic web application often means database at the back-end. It not only takes data from the database and shows, but also collects data from the visitors. For example, you want to add a quick survey into your Joomla! Site. Instead of searching for different extensions for survey forms, you can quickly build one survey form using an extension named CK Forms. This extensions is freely available for download at http://ckforms.cookex.eu/download/download.php. For building a quick survey, follow the steps below: Download CK Forms extension from http://ckforms.cookex.eu/download/download.php and install it from Extensions | Install/Uninstall screen in Joomla! Administration area. Once installed successfully, you see the component CK Forms in Components menu. Select Components | CK Forms and you get CK Forms screen as shown below: For creating a new form, click on New icon in the toolbar. That opens up CK Forms: [New] screen. In the General tab, type the name and title of the form. The name should be without space, but title can be fairly long and with spaces. Then select Yes in Published field if you want to show the form now. In Description field, type a brief description of the form which will be displayed before the form. In Results tab, select Yes in Save result field. This will store the data submitted by the form into database and allow you to see the data later. In Text result field, type the text that you want to display just after submission of the form. In Redirect URL field, type the URL of a page where the user will be redirected after submitting the form. In E-mail tab, select Yes in Email result field, if you want the results of the forms to be e-mailed to you. If you select Yes in this field, provide mail-to, mail cc, and Mail BCC address. Also specify subject of the mail in Mail subject field. Select Yes in Include fileupload file field if you want the uploaded file to be mailed too. If an e-mail field is present in the form and the visitor submits his/her e-mail address, you can send an acknowledgement on receiving his/her data through e-mail. For sending such receipt messages, select Yes in E-mail receipt field. Then specify e-mail receipt subject and e-mail receipt text. You can also include the data and file submitted via the form with this receipt e-mail. For doing so, select Yes in both Include data and Include fileupload file fields. In Advanced tab, you can specify whether you want to use Captcha or not. Select Yes in Use Captcha field. Then type some tips text in Captcha tips text, for example, 'Please type the text shown in the image'. You can also specify error texts in Captcha custom error text field. In Uploaded files path field, you can specify where the files uploaded by the users will be stored. The directory mentioned here must be writable. You can also specify the maximum size of uploaded file in File uploaded maximum size field. To display Powered by CK Forms text below the form, select Yes in Display "Powered by" text field. In Front-end display tab, you can choose to display IP address of the visitor. You can view help on working with CK Forms by clicking on Help tab. After filling up all the fields, click on Save icon in the toolbar. That will save the form and take you to CK Forms screen. Now you will see the newly created form listed in this screen.
Read more
  • 0
  • 0
  • 11906

article-image-configuring-jboss-application-server-5
Packt
05 Jan 2010
7 min read
Save for later

Configuring JBoss Application Server 5

Packt
05 Jan 2010
7 min read
JBoss Web Server currently uses the Apache Tomcat 6.0 release and it is ships as service archive (SAR) application in the deploy folder. The location of the embedded web server has changed at almost every new release of JBoss. The following table could be a useful reference if you are using different versions of JBoss: JBoss release Location of Tomcat 5.0.0 GA deploy/jbossweb.sar 4.2.2 GA deploy/jboss-web.deployer 4.0.5 GA deploy/jbossweb-tomcat55.sar 3.2.X deploy/jbossweb-tomcat50.sar The main configuration file is server.xml which, by default, has the following minimal configuration: <Server><Listener className="org.apache.catalina.core.AprLifecycleListener"SSLEngine="on" /><Listener className="org.apache.catalina.core.JasperListener" /><Service name="jboss.web"><Connector protocol="HTTP/1.1" port="8080"address="${jboss.bind.address}"connectionTimeout="20000" redirectPort="8443" /><Connector protocol="AJP/1.3" port="8009"address="${jboss.bind.address}"redirectPort="8443" /><Engine name="jboss.web" defaultHost="localhost"><Realm className="org.jboss.web.tomcat.security.JBossWebRealm"certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly" /><Host name="localhost"><Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve"cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager"transactionManagerObjectName="jboss:service=TransactionManager" /></Host></Engine></Service></Server> Following is a short description for the key elements of the configuration: Element Description Server The Server is Tomcat itself, that is, an instance of the web application server and is a top-level component. Service An Engine is a request-processing component that represents the Catalina servlet engine. It examines the HTTP headers to determine the virtual host or context to which requests should be passed. Connector It's the gateway to Tomcat Engine. It ensures that requests are received from clients and are assigned to the Engine. Engine Engine handles all requests. It examines the HTTP headers to determine the virtual host or context to which requests should be passed. Host One virtual host. Each virtual host is differentiated by a fully qualified hostname. Valve A component that will be inserted into the request processing pipeline for the associated Catalina container. Each Valve has distinct processing capabilities. Realm It contains a set of users and roles. As you can see, all the elements are organized in a hierarchical structure where the Server element acts as top-level container: The lowest elements in the configuration are Valve and Realm, which can be nested into Engine or Host elements to provide unique processing capabilities and role management. Customizing connectors Most of the time when you want to customize your web container, you will have to change some properties of the connector. <Connector protocol="HTTP/1.1" port="8080"address="${jboss.bind.address}"connectionTimeout="20000" redirectPort="8443" /> A complete list of the connector properties can be found on the Jakarta Tomcat site (http://tomcat.apache.org/). Here, we'll discuss the most useful connector properties: port: The TCP port number on which this connector will create a server socket and await incoming connections. Your operating system will allow only one server application to listen to a particular port number on a particular IP address. acceptCount: The maximum queue length for incoming connection requests, when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 10. connectionTimeout: The number of milliseconds the connector will wait after accepting a connection for the request URI line to be presented. The default value is 60000 (that is, 60 seconds). address: For servers with more than one IP address, this attribute specifies which address will be used for listening on the specified port. By default, this port will be used on all IP addresses associated with the server. enableLookups: Set to true if you want to perform DNS lookups in order to return the actual hostname of the remote client and to false in order to skip the DNS lookup and return the IP address in string form instead (thereby improving performance). By default, DNS lookups are enabled. maxHttpHeaderSize: The maximum size of the request and response HTTP header, specified in bytes. If not specified, this attribute is set to 4096 (4 KB). maxPostSize: The maximum size in bytes of the POST, which will be handled by the container FORM URL parameter parsing. The limit can be disabled by setting this attribute to a value less than or equal to zero. If not specified, this attribute is set to 2097152 (2 megabytes). maxThreads: The maximum number of request processing threads to be created by this connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. The new Apache Portable Runtime connector Apache Portable Runtime (APR) is a core Apache 2.x library designed to provide superior scalability, performance, and better integration with native server technologies. The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations. The primary goal is to provide an API to which software developers may code and be assured of predictable if not identical behaviour regardless of the platform on which their software is built, relieving them of the need to code special-case conditions to work around or take advantage of platform-specific deficiencies or features. The high-level performance of the new APR connector is made possible by the introduction of socket pollers for persistent connections (keepalive). This increases the scalability of the server, and by using sendfile system calls, static content is delivered faster and with lower CPU utilization. Once you have set up the APR connector, you are allowed to use the following additional properties in your connector: keepAliveTimeout: The number of milliseconds the APR connector will wait for another HTTP request, before closing the connection. If not set, this attribute will use the default value set for the connectionTimeout attribute. pollTime: The duration of a poll call; by default it is 2000 (5 ms). If you try to decrease this value, the connector will issue more poll calls, thus reducing latency of the connections. Be aware that this will put slightly more load on the CPU as well. pollerSize: The number of sockets that the poller kept alive connections can hold at a given time. The default value is 768, corresponding to 768 keepalive connections. useSendfile: Enables using kernel sendfile for sending certain static files. The default value is true. sendfileSize: The number of sockets that the poller thread dispatches for sending static files asynchronously. The default value is 1024. If you want to consult the full documentation of APR, you can visit http://apr.apache.org/. Installing the APR connector In order to install the APR connector, you need to add some native libraries to your JBoss server. The native libraries can be found at http://www.jboss.org/jbossweb/downloads/jboss-native/. Download the version that is appropriate for your OS. Once you are ready, you need to simply unzip the content of the archive into your JBOSS_HOME directory. As an example, Unix users (such as HP users) would need to perform the following steps: cd jboss-5.0.0.GAtar tvfz jboss-native-2.0.6-hpux-parisc2-ssl.tar.gz Now, restart JBoss and, from the console, verify that the connector is bound to Http11AprProtocol. A word of caution!At the time of writing, the APR library still has some open issues that prevent it from loading correctly on some platforms, particularly on the 32-bit Windows. Please consult the JBoss Issue Tracker (https://jira.jboss.org/jira/secure/IssueNavigator.jspa?) to verify that there are no open issues for your platform.
Read more
  • 0
  • 0
  • 4635
article-image-searching-data-microsoft-dynamics-ax-2009-part-1
Packt
31 Dec 2009
10 min read
Save for later

Searching for Data in Microsoft Dynamics AX 2009: Part 1

Packt
31 Dec 2009
10 min read
Queries Queries are typically used to ask users about ranges and sorting, and then selecting data based on the feedback from the users. A query can consist of one or multiple data sources, and can be created both as static queries in the AOT or as dynamic queries using X++. Most commonly they are used when the ranges or values are not known until runtime. Static queries are defined in the AOT, whereas dynamic queries are defined in X++ code. Creating a static query using the AOT Follow these steps to create a static query in the AOT: Open the AOT, expand the Queries node, right-click on Queries, and select New Query. A new query is then created in the AOT. Right-click on the query, select Properties, and change the name to CarList (or in other cases, to something that describes what kind of data the query is returning). Open a new AOT window, expand the DataDictionary node, and then expand the Tables node. Drag the CarTable and drop it onto the Data Sources node of the new query. You can also drag maps or views to the data source of a query. You have now created the skeleton of the query. Let's now look at how to add sorting and ranges to the query. Adding a sort order to the query To add a sorting to the query, just drag the selected field from the Fields node under the data source and drop it under the Order By node. In our example, we'll use the Mileage field. You can then select to have it sort ascending or descending by changing the direction property on the sort field. When the query prompt is executed in a report, the user has the ability to change the sort order. Adding a range to the query You can also add ranges to the data source by dragging a field from the Fields node and dropping it onto the ranges. A range can be used to narrow down the result returned by the query, or it can be used as a fixed range that the user cannot change. This is done by adding a value to the value property of the range. Values in a range can be used like this: Range operator Description Example , Selects records where the range field matches any of the values listed BMW, VW, Volvo = Selects records where the range field is a matching value =VW .. Selects records where the range field is between the values specified including the values used. 1000..3000 < Selects records where the range field is less than the value specified <2000 > Selects records where the range field is greater than the value specified >2000 ! Selects records where the range field is not equal to the value specified !BMW ? Selects records where the ? can be any character Merc??es * Selects records where the range field matches the characters before or after the asterisk Merc* When the Status property is set to Open, the users can change the range value. If it's set to Lock, the users can see the range value before executing the query, but they are not allowed to change it. If the status property is set to Hide, the users won't even be allowed to see the range value. In our example, we add the ModelYear field from the data source CarTable_1: Joining data sources in a query In order to select data from more than one table, you can join the data sources in your query. Data sources can be joined in a couple of different ways depending on how you would like to link them. This is done by setting the JoinMode property to the different values shown in the following table: JoinMode Description InnerJoin Will return the records where the joined data sources have matching values in the joined fields. Ex: By using the CarTable as the primary data source and using RentalTable as the joined data source, the inner join will fetch all records from the CarTable where there is a corresponding record in the RentalTable. The corresponding records in RentalTable will also be fetched. OuterJoin Will return all the records from the joined table even if they don't match the joined field. Ex: Compared to the example using the InnerJoin, this will return all records from the CarTable, but also records from the RentalTable that does not have a match in the CarTable. ExistsJoin This is just like the InnerJoin, except the records from the joined data source are not returned. They are only used to filter the primary data source. Ex: In our example it will only return records in the CarTable where there is a match in the RentalTable. Records from the RentalTable will not be fetched. NoExistsJoin This is the opposite of ExistsJoin. It will select records from the primary data source when matching records in the joined data source does not exist. Ex: In our example it will return records from the CarTable that did not have any matching records in the RentalTable. (Cars that has never been rented) Follow these steps to add a new data source and join it with the first one: First, we will create a duplicate of the query that we have created so far, as we would like to use the original query in the Reporting Services report. To duplicate any AOT object, right-click on the object and select Duplicate. A duplicate is then created with the prefix CopyOf. Now rename the new query to RentalCarList. Also, change the range under the CarTable_1 data source to ModelYear instead of Model. This range will be used later in this article. Drag another table, map, or view, and drop it onto the Data Sources node below the first data source. In our example, we will add the RentalTable. Therefore, open a new AOT window and browse to Data Dictionary | Tables | RentalTable. Drag the RentalTable and drop it onto the Data Sources node under the CarTable data source in the query. Open the properties of the RentalTable data source in the query and change the Relations property to Yes. If you expand the Relations node under the RentalTable data source, you should now see that the CarTable data source is linked to the RentalTable data source by the CarId. Your AOT should look like this: Creating a dynamic query using X++ A query can also be built dynamically using X++ code. This can be the only way of creating the query, if you would like the query to work in one way in some cases and in another way in other cases. An example can be where you would like to join one table if one condition is true and another table if the condition is false. To do this, you need to understand how the query object model works. The most commonly used classes in the query object model are: Query: Contains the definition of the query. Can consist of one data source or several data sources if they are related. QueryRun: Class used to execute the query and loop through the result. QueryBuildDataSource: Links to one data source in the query. Can be linked to another QueryBuildDataSource object to join linked data sources. QueryBuildRange: Enables the end user to limit the result by adding a value in the specified query range. QueryBuildFieldList: List of all the fields in data source. OneQueryBuildFieldList object for each QueryBuildDataSource. By default the property Dynamic is set to true so that all fields are returned. QueryBuildLink: Links two data sources in a join. Is set on the child data source. The query definition is set up by creating and linking objects from the query object model together. The following example shows how this is done in order to create a similar query as we did in the previous section of this article when we created a query called RentalCarList in the AOT. static void queryRentalCarList(Args _args){Query query;QueryBuildDataSource queryBuildDataSource1,queryBuildDataSource2;QueryBuildRange queryBuildRange;QueryBuildLink queryBuildLink;;// Create a new query objectquery = new Query();// Add the first data source to the queryqueryBuildDataSource1 = query.addDataSource(tablenum(CarTable));// Add the range to this first data sourcequeryBuildRange = queryBuildDataSource1.addRange(fieldnum(CarTable, ModelYear));// Add the second datasource to the first data sourcequeryBuildDataSource2 =queryBuildDataSource1.addDataSource(tablenum(RentalTable));// Add the link from the child data source to the//parent datasourcequeryBuildLink = queryBuildDataSource2.addLink(fieldnum(CarTable,CarId),fieldnum(RentalTable, CarId));} Using a query Ok, so now we have the query definition. But that doesn't help us much unless we are able to execute the query, right? This example uses the previous example and just adds the QueryRun object and loops through the result by using the next() method on the QueryRun object. static void queryRunRentalCarList(Args _args){Query query;QueryBuildDataSource queryBuildDataSource1,queryBuildDataSource2;QueryBuildRange queryBuildRange;QueryBuildLink queryBuildLink;QueryRun queryRun;CarTable carTable;RentalTable rentalTable;;// Create a new query objectquery = new Query();// Add the first data source to the queryqueryBuildDataSource1 = query.addDataSource(tablenum(CarTable));// Add the range to this first data sourcequeryBuildRange = queryBuildDataSource1.addRange(fieldnum(CarTable, ModelYear));// Set the rangequeryBuildRange.value("2008..");// Add the second datasource to the first data sourcequeryBuildDataSource2 =queryBuildDataSource1.addDataSource(tablenum(RentalTable));// Add the link from the child data source to the parent data//sourcequeryBuildLink = queryBuildDataSource2.addLink(fieldnum(CarTable,CarId),fieldnum(RentalTable, CarId));// Create a new QueryRun object based on the query definitionqueryRun = new QueryRun(query);// Loop through all the records returned by the querywhile (queryRun.next()){// Get the table data by using the get() methodcarTable = queryRun.get(tablenum(CarTable));rentalTable = queryRun.get(tablenum(RentalTable));info (strfmt("CarId %1, RentalId %2", carTable.CarId,rentalTable.RentalId));}} The following result is obtained after running the query: The exact same result will show up if we execute the query that was defined in the AOT in the previous section of this article. The code would then look like this: static void queryRunRentalCarListAOT(Args _args){Query query;QueryBuildDataSource queryBuildDataSource;QueryBuildRange queryBuildRange;QueryRun queryRun;CarTable carTable;RentalTable rentalTable;;// Create a new query object based on the Query in the AOT called//RentalCarListquery = new Query(querystr(RentalCarList));// Find the datasource for the CarTablequeryBuildDataSource = query.dataSourceTable(tablenum(CarTable));// Find the range that we added to the query in the AOTqueryBuildRange =queryBuildDataSource.findRange(fieldnum(CarTable, ModelYear));// Set the value of the rangequeryBuildRange.value("2008..");// Create a new QueryRun object based on the query definitionqueryRun = new QueryRun(query);// Loop through all the records returned by the querywhile (queryRun.next()){// Get the table data by using the get() methodcarTable = queryRun.get(tablenum(CarTable));rentalTable = queryRun.get(tablenum(RentalTable));info (strfmt("CarId %1, RentalId %2", carTable.CarId,rentalTable.RentalId));}} Views Views in AX are objects that are used to retrieve data from the database that is stored in the memory on the layer in which the view is instantiated. The views are actually stored as database views on the SQL server. This means that there are potentially great performance benefits of using views compared to using an equivalent query. This depends of course on the complexity of the query, but in general the performance benefits of using a view compared to a query will increase along with the complexity of the query. Views can be used throughout AX in all places where tables can be used. This includes forms, queries, reports, and X++ code. Views in AX can never be used to write data, only to read data from the database. This differs from the SQL implementation that has write-back possibilities for views.
Read more
  • 0
  • 0
  • 7287

article-image-calendaring-plone-3-education
Packt
31 Dec 2009
6 min read
Save for later

Calendaring with Plone 3 for Education

Packt
31 Dec 2009
6 min read
(For more resources on Plone, see here.) The techniques in this article are applicable in many organizational schemes. We present one common arrangement as an example: a top-level folder where visitors can browse the highest-profile events on the site. Show events on a calendar Plone's out-of-the-box Events folder provides a basic way to find events: it displays them in a chronological list broken into pages of 20 each. While fine for simple cases, this is cumbersome for visitors who want to look at events for a certain future date. Part of our goal is to set up a monthly calendar to make this common case easy: Our first step toward the monthly calendar is to replace Plone's stock Events folder. Out of the box, it holds individual events along with a summarizing collection that acts as its front page. If you don't need a drill-down way of browsing your events by subject—for example, if you have so few that they all fit comfortably on a calendar like the above—you can leave the default Events folder in place. Otherwise, follow the instructions below to replace it with a standalone collection; this will interact better with Plone's navigation portlet, which we will use to implement the drilldown browsing. If you choose to stick with the stock Events folder, you may still wish to adjust the criteria of its inner collection as described in the following: First, delete the Events folder. Replace it with a new collection called "Events". Give it an Item Type criterion, and tell it to pull in everything of the type Event. The original Events collection had a Start Date criterion to keep past events off the page. We won't need that, since the calendar view we are about to apply keeps past events tucked away implicitly—and we do want the ability to see old events when we navigate to previous months. The original collection also had a State criterion that limited it to showing published events. If you need only to hide unpublished events from visitors, then you can dispense with this: the internal search routines used by the collection will naturally show only what the current user has permission to see. Preventing a common contributor errorOften, a less proficient contributor will add an event, see it on his or her own calendar, and move on, neglecting to publish it. Adding the State criterion can serve as a reminder, preventing the event from appearing until properly published. The downside is that it makes the calendar useless for intranets: Events that aren't publicly visible will never show up. But if you have no non-public events to list, consider recreating the State criterion. If you never want to show access-controlled events on the main calendar add a State criterion limiting the collection to published items. The Events collection is finished. Next, we apply a monthly calendar view to our data. Meet Plone4Artists Calendar Plone's built-in event listings are rather basic. We need to do special tricks with collections and default views just to sort them in chronological order. At best, this is several extra clicks, and, at worst, it can confuse your less technical content contributors. A third-party product called Plone4Artists Calendar makes this easy and gives us several other capabilities to boot. Plone4Artists Calendar is the current frontrunner in the Plone calendaring space. It provides... Daily, weekly, monthly, and a few other calendar-like views for folders and collections Rudimentary recurring event support Hooks for pulling events from other systems in realtime, with a bit of coding Don't let the name "Plone4Artists" put you off if you aren't an artist; though the Plone4Artists suite of products came out of a project to provide artist community web sites, there's nothing particularly artist-centric about them. In fact, there has been discussion about renaming them. The runner up: CalendarXThe other Plone calendar worth considering is CalendarX, whose most recent release at the time of this writing is 0.9.1. 0.9.0 was the first update to the product since since 2005 and represents a major refit. Its ancient data-modeling internals were replaced with a modern Archetypes implementation, and one no longer needed to venture into the ZMI to do simple configuration. Speaking of configuration, CalendarX exposes a lot of it: 6 tabs packed with options for tweaking calendar format, event display, widgets, and more. There are 57 options alone regarding its CSS cosmetics. If you need a specific look and aren't comfortable writing your own CSS or template code, CalendarX may be the ticket.However, be warned that CalendarX has a history of being sporadically maintained. It lacked Plone 3 compatibility for a long time, and compatibility work began only when a group of stranded Plone 2.5 users at Pennsylvania State University put a week of development work toward it. Its internals still hold a lot of legacy that may prove difficult to maintain as Plone evolves.Plone4Artists Calendar, on the other hand, is a simpler product—both inside and outside and with all the good and bad that entails—and the winds of further community effort are blowing in its direction. Its maintainable design and the willingness of developers to work on it make it the solution least likely to leave you stranded; this is why it is our recommendation in this article. Install Plone4Artists Calendar Before we can make use of its views, we need to install the product—actually, two products and several supporting packages. Weave these directives into the proper sections of your buildout.cfg... [buildout]...other directives...eggs = ...other eggs here... p4a.plonecalendar p4a.ploneevent[instance]...other directives...zcml = ...other ZCML listings here... # Plone4Artists Calendar doesn't support Plone 3.3's auto-ZCMLloading as of 2.0a2. p4a.plonecalendar-meta p4a.plonecalendar p4a.ploneevent[productdistros]recipe = plone.recipe.distrosurls =http://plone.org/products/calendaring/releases/0.4/calendaring-0-4-0.tgz ...run buildout, restart Zope/Plone, and install the Plone4ArtistsCalendar (p4a.plonecalendar) and Recurring Events (p4a.ploneevent) products in Site Setup → Add-on Products. Now that everything is installed, we apply a monthly calendar view to the Events collection: Navigate back to the Events collection, and choose Calendar from the new Sub-types menu. If it isn't already selected, choose Month view from the Display menu. Presto—we have a monthly calendar showing every event on our site.
Read more
  • 0
  • 0
  • 7614
Modal Close icon
Modal Close icon