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-yui-2x-using-event-component
Packt
14 Dec 2010
7 min read
Save for later

YUI 2.X: Using Event Component

Packt
14 Dec 2010
7 min read
Yahoo! User Interface Library 2.x Cookbook Over 70 simple incredibly effective recipes for taking control of Yahoo! User Interface Library like a Pro Easily develop feature-rich internet applications to interact with the user using various built-in components of YUI library Simple and powerful recipes explaining how to use and implement YUI 2.x components Gain a thorough understanding of the YUI tools Plenty of example code to help you improve your coding and productivity with the YUI Library Hands-on solutions that take a practical approach to recipes In this article, you will learn how to use YUI to handle JavaScript events, what special events YUI has to improve the functionality of some JavaScript events, and how to write custom events for your own application. Using YUI to attach JavaScript event listeners When attaching events in JavaScript most browsers use the addEventListener function , but the developers of IE use a function called attachEvent. Legacy browsers do not support either function, but instead require developers to attach functions directly to element objects using the 'on' + eventName property (for example myElement.onclick=function(){...}). Additionally, the execution context of event callback functions varies depending on how the event listener is attached. The Event component normalizes all the cross-browser issues, fixes the execution context of the callback function, and provides additional event improvements. This recipe will show how to attach JavaScript event listeners, using YUI. How to do it... Attach a click event to an element: var myElement = YAHOO.util.Dom.get('myElementId'); var fnCallback = function(e) { alert("myElementId was clicked"); }; YAHOO.util.Event.addListener(myElement, 'click', fnCallback); Attach a click event to an element by its ID: var fnCallback = function(e) { alert("myElementId was clicked"); }; YAHOO.util.Event.addListener('myElementId','click',fnCallback) Attach a click event to several elements at once: var ids = ["myElementId1", "myElementId2", "myElementId3"]; var fnCallback = function(e) { var targ = YAHOO.util.Event.getTarget(e); alert(targ.id + " was clicked"); }; YAHOO.util.Event.addListener(ids, 'click', fnCallback); When attaching event listeners, you can provide an object as the optional fourth argument, to be passed through as the second argument to the callback function: var myElem = YAHOO.util.Dom.get('myElementId'); var fnCallback = function(e, obj) { alert(obj); }; var obj = "I was passed through."; YAHOO.util.Event.addListener(myElem,'click',fnCallback,obj); When attaching event listeners, you can change the execution context of the callback function to the fourth argument, by passing true as the optional fifth argument: var myElement = YAHOO.util.Dom.get('myElementId'); var fnCallback = function(e) { alert('My execution context was changed.'); }; var ctx = { /* some object to be the execution context of callback */ }; YAHOO.util.Event.addListener( myElement, 'click', fnCallback, ctx, true); How it works... The addListener function wraps the native event handling functions, normalizing the cross- browser differences. When attaching events, YUI calls the correct browser specific function, or defaults to legacy event handlers. Before executing the callback function, the Event component must (in some browsers) find the event object and adjust the execution context of the callback function. The callback function is normalized by wrapping it in a closure function that executes when the browser event fires, thereby allowing YUI to correct the event, before actually executing the callback function. In legacy browsers, which can only have one callback function per event type, YUI attaches a callback function that iterates through the listeners attached by the addListener function There's more... The addListener function returns true if the event listener is attached successfully and false otherwise. If the element to listen on is not available when the addListener function is called, the function will poll the DOM and wait to attach the listener when the element becomes available. Additionally, the Event component also keeps a list of all events that it has attached. This list is maintained to simplify removing events listeners, and so that all event listeners can be removed when the end-user leaves the page. Find all events attached to an element: var listeners = YAHOO.util.Event.getListeners('myElementId'); for (var i=0,j=listeners.length; i<j; i+=1) { var listener = listeners[i]; alert(listener.type); // event type alert(listener.fn); // callback function alert(listener.obj); // second argument of callback alert(listener.adjust); // execution context } Find all events of a certain type attached to an element: // only click listeners var listeners = YAHOO.util.Event.getListeners('myElementId', 'click'); The garbage collector in JavaScript does not always do a good job cleaning up event handlers. When removing nodes from the DOM, remember to remove events you may have added as well. More on YAHOO.util.Event.addListener The addListener function has been aliased by the shorter on function: var myElement = YAHOO.util.Dom.get('myElementId'); var fnCallback = function(e) { alert("myElementId was clicked"); }; YAHOO.util.Event.on(myElement, 'click', fnCallback); By passing an object in as the optional fifth argument of addListener, instead of a Boolean, you can change the execution context of the callback to that object, while still passing in an another object as the optional fourth argument: var myElement = YAHOO.util.Dom.get('myElementId'); var fnCallback = function(e, obj) { // this executes in the context of 'ctx' alert(obj); }; var obj = "I was passed through."; var ctx = { /* some object to be the execution context of callback */ }; YAHOO.util.Event.addListener( myElement,'click',fnCallback,obj, ctx); Lastly, there is an optional Boolean value that can be provided as the sixth argument of addListener, which causes the callback to execute in the event capture phase, instead of the event bubbling phase. You probably won't ever need to set this value to true, but if you want to learn more about JavaScript event phases see: http://www.quirksmode.org/js/events_order.html Event normalization functions The event object, provided as the first argument of the callback function, contains a variety of values that you may need to use (such as the target element, character code, etc.). YUI provides a collection of static functions that normalizes the cross-browser variations of these values. Before trying to use these properties, you should read this recipe, as it walks you through each of those functions. How to do it... Fetch the normalized target element of an event: var fnCallback = function(e) { var targetElement = YAHOO.util.Event.getTarget(e); alert(targetElement.id); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); Fetch the character code of a key event (also known as the key code): var fnCallback = function(e) { var charCode = YAHOO.util.Event.getCharCode(e); alert(charCode); }; YAHOO.util.Event.on('myElementId', 'keypress', fnCallback); Fetch the x and y coordinates of a mouse event: var fnCallback = function(e) { var x = YAHOO.util.Event.getPageX(e); var y = YAHOO.util.Event.getPageY(e); alert("x-position=" + x + " and x-position= " + y); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); Fetch both the x and y coordinates of a mouse event, using: var fnCallback = function(e) { var point = YAHOO.util.Event.getXY(e); alert("x-position="+point[0]+" and x-position= "+point[1]); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); Fetch the normalized related target element of an event: var fnCallback = function(e) { var targetElement = YAHOO.util.Event.getRelatedTarget(e); alert(targetElement.id); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); Fetch the normalized time of an event: var fnCallback = function(e) { var time = YAHOO.util.Event.getTime(e); alert(time); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); Stop the default behavior, propagation (bubbling) of an event, or both: var fnCallback = function(e) { // prevents the event from bubbling up to ancestors YAHOO.util.Event.stopPropagation(e); // prevents the event's default YAHOO.util.Event.preventDefault(e); // prevents the event's default behavior and bubbling YAHOO.util.Event.stopEvent(e); }; YAHOO.util.Event.on('myElementId', 'click', fnCallback); How it works... All of these functions test to see if a value exists on the event for each cross-browser variation of a property. The functions then normalize those values and return them. The stopPropogation and preventDefault functions actually modify the equivalent cross-browser property of the event, and delegate the behavior to the browsers.
Read more
  • 0
  • 0
  • 3243

article-image-ibm-cognos-workspace-advanced
Packt
14 Jun 2013
5 min read
Save for later

IBM Cognos Workspace Advanced

Packt
14 Jun 2013
5 min read
(For more resources related to this topic, see here.) Who should use Cognos Workspace Advanced? With Cognos Workspace Advanced, business users have one tool for creating advanced analyses and reports. The tool, like Query Studio and Analysis Studio, is designed for ease of use and is built on the same platform as the other report development tools in Cognos. Business Insight Advanced/Cognos Workspace Advanced is actually so powerful that it is being positioned more as a light Cognos Report Studio than as a powerful Cognos Query Studio and Cognos Analysis Studio. Comparing to Cognos Query Studio and Cognos Analysis Studio With so many options for business users, how do we know which tool to use? The best approach for making this decision is to consider the similarities and differences between the options available. In order to help us do so, we can use the following table: Feature Query Studio Analysis Studio Cognos Workspace Advanced Ad hoc reporting X   X Ad hoc analysis   X X Basic charting X X X Advanced charting     X Basic filtering X X X Advanced filtering     X Basic calculations X X X Advanced calculations     X Properties pane     X External data     X Freeform design     X As you can see from the table, all three products have basic charting, basic filtering, and basic calculation features. Also, we can see that Cognos Query Studio and Cognos Workspace Advanced both have ad hoc reporting capabilities, while Cognos Analysis Studio and Cognos Workspace Advanced both have ad hoc analysis capabilities. In addition to those shared capabilities, Cognos Workspace Advanced also has advanced charting, filtering, and calculation features. Cognos Workspace Advanced also has a limited properties pane (similar to what you would see in Cognos Report Studio). Furthermore, Cognos Workspace Advanced allows end users to bring in external data from a flat file and merge it with the data from Cognos Connection. Finally, Cognos Workspace Advanced has free-form design capabilities. In other words, you are not limited in where you can add charts or crosstabs in the way that Cognos Query Studio and Cognos Analysis Studio limit you to the standard templates. The simple conclusion after performing this comparison is that you should always use Cognos Workspace Advanced. While that will be true for some users, it is not true for all. With the additional capabilities come additional complexities. For your most basic business users, you may want to keep them using Cognos Query Studio or Cognos Analysis Studio for their ad hoc reporting and ad hoc analysis simply because they are easier tools to understand and use. However, for those business users with basic technical acumen, Cognos Workspace Advanced is clearly the superior option. Accessing Cognos Workspace Advanced I would assume now that, after reviewing the capabilities Cognos Workspace Advanced brings to the table, you are anxious to start using it. We will start off by looking at how to access the product. The first way to access Cognos Workspace Advanced is through the welcome page. On the welcome page, you can get to Cognos Workspace Advanced by clicking on the option Author business reports: This will bring you to a screen where you can select your package. In Cognos Query Studio or Cognos Analysis Studio, you will only be able to select non-dimensional and dimensional packages based on the tool you are using. With Cognos Workspace Advanced, because the tool can use both dimensional and non-dimensional packages, you will be prompted with packages for both. The next way to access Cognos Workspace Advanced is through the Launch menu in Cognos Connection. Within the menu, you can simply choose Cognos Workspace Advanced to be taken to the same options for choosing a package. Note, however, that if you have already navigated into a package, it will automatically launch Cognos Workspace Advanced using the very same package. The third way to access Cognos Workspace Advanced is by far the most functional way. You can actually access Cognos Workspace Advanced from within Cognos Workspace by clicking on the Do More... option on a component of the dashboard: When you select this option, the object will expand out and open for editing inside Cognos Workspace Advanced. Then, once you are done editing, you can simply choose the Done button in the upper right-hand corner to return to Cognos Workspace with your newly updated object. For the sake of showing as many features as possible in this chapter, we will launch Cognos Workspace Advanced from the welcome page or from the Launch menu and select a package that has an OLAP data source. For the purpose of following along, we will be using the Cognos BI sample package great_outdoors_8 (or Great Outdoors). When we first access it, we are prompted to choose a package. For these examples, we will choose great_outdoors_8: We are then brought to a splash screen where we can choose Create new or Open existing. We will choose Create new. We are then prompted to pick the type of chart we want to create. As we will see from the following screenshot, our options are: Blank: It starts us off with a completely blank slate List: It starts us off with a list report Crosstab: It starts us off with a crosstab Chart: It starts us off with a chart and loads the chart wizard Financial: It starts us off with a crosstab formatted like a financial report Existing...: It allows us to open an existing report We will choose Blank because we can still add as many of the other objects as we want to later on.
Read more
  • 0
  • 0
  • 3242

article-image-handling-invalid-survey-submissions-django
Packt
20 Apr 2010
5 min read
Save for later

Handling Invalid Survey Submissions with Django

Packt
20 Apr 2010
5 min read
What would make a survey submission invalid? The only likely error case for our QuestionVoteForm is if no answer is chosen. What happens, then, if we attempt to submit a survey with missing answers? If we try it, we see that the result is not ideal: There are at least two problems here. First, the placement of the error messages, above the survey questions, is confusing. It is hard to know what the first error message on the page is referring to, and the second error looks like it is associated with the first question. It would be better to move the error messages closer to where the selection is actually made, such as between the question and answer choice list. Second, the text of the error message is not very good for this particular form. Technically the list of answer choices is a single form field, but to a general user the word field in reference to a list of choices sounds odd. We will correct both of these errors next. Coding custom error message and placement Changing the error message is easy, since Django provides a hook for this. To override the value of the error message issued when a required field is not supplied, we can specify the message we would like as the value for the required key in an error_messages dictionary we pass as an argument in the field declaration. Thus, this new definition for the answer field in QuestionVoteForm will change the error message to Please select an answer below: class QuestionVoteForm(forms.Form): answer = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=None, empty_label=None, error_messages={'required': 'Please select an answer below:'}) Changing the placement of the error message requires changing the template. Instead of using the as_p convenience method, we will try displaying the label for the answer field, errors for the answer field, and then the answer field itself, which displays the choices. The {% for %} block that displays the survey forms in the survey/active_survey.html template then becomes: {% for qform in qforms %} {{ qform.answer.label }} {{ qform.answer.errors }} {{ qform.answer }}{% endfor %} How does that work? Better than before. If we try submitting invalid forms now, we see: While the error message itself is improved, and the placement is better, the exact form of the display is not ideal. By default, the errors are shown as an HTML unordered list. We could use CSS styling to remove the bullet that is appearing (as we will eventually do for the list of choices), but Django also provides an easy way to implement custom error display, so we could try that instead. To override the error message display, we can specify an alternate error_class attribute for QuestionVoteForm, and in that class, implement a __unicode__ method that returns the error messages with our desired formatting. An initial implementation of this change to QuestionVoteForm and the new class might be: class QuestionVoteForm(forms.Form): answer = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=None, empty_label=None, error_messages={'required': 'Please select an answer below:'}) def __init__(self, question, *args, **kwargs): super(QuestionVoteForm, self).__init__(*args, **kwargs) self.fields['answer'].queryset = question.answer_set.all() self.fields['answer'].label = question.question self.error_class = PlainErrorListfrom django.forms.util import ErrorListclass PlainErrorList(ErrorList): def __unicode__(self): return u'%s' % ' '.join([e for e in sefl]) The only change to QuestionVoteForm is the addition of setting its error_class attribute to PlainErrorList in its __init__ method. The PlainErrorList class is based on the django.form.util.ErrorList class and simply overrides the __unicode__ method to return the errors as a string with no special HTML formatting. The implementation here makes use of the fact that the base ErrorList class inherits from list, so iterating over the instance itself returns the individual errors in turn. These are then joined together with spaces in between, and the whole string is returned. Note that we're only expecting there to ever be one error here, but just in case we are wrong in that assumption, it is safest to code for multiple errors existing. Although our assumption may never be wrong in this case, it's possible we might decide to re-use this custom error class in other situations where the single possible error expectation doesn't hold. If we code to our assumption and simply return the first error in the list, this may result in confusing error displays in some situations where there are multiple errors, since we will have prevented reporting all but the first error. If and when we get to that point, we may also find that formatting a list of errors with just spaces intervening is not a good presentation, but we can deal with that later. First, we'd like to simply verify that our customization of the error list display is used.
Read more
  • 0
  • 0
  • 3241

Packt
09 Feb 2016
13 min read
Save for later

CSS Properties – Part 1

Packt
09 Feb 2016
13 min read
In this article written by Joshua Johanan, Talha Khan and Ricardo Zea, authors of the book Web Developer's Reference Guide, the authors wants to state that "CSS properties are characteristics of an element in a markup language (HTML, SVG, XML, and so on) that control their style and/or presentation. These characteristics are part of a constantly evolving standard from the W3C." (For more resources related to this topic, see here.) A basic example of a CSS property is border-radius: input { border-radius: 100px; } There is an incredible amount of CSS properties, and learning them all is virtually impossible. Adding more into this mix, there are CSS properties that need to be vendor prefixed (-webkit-, -moz-, -ms-, and so on), making this equation even more complex. Vendor prefixes are short pieces of CSS that are added to the beginning of the CSS property (and sometimes, CSS values too). These pieces of code are directly related to either the company that makes the browser (the "vendor") or to the CSS engine of the browser. There are four major CSS prefixes: -webkit-, -moz-, -ms- and -o-. They are explained here: -webkit-: This references Safari's engine, Webkit (Google Chrome and Opera used this engine in the past as well) -moz-: This stands for Mozilla, which creates Firefox -ms-: This stands for Microsoft, which creates Internet Explorer -o-: This stands for Opera, but only targets old versions of the browser Google Chrome and Opera both support the -webkit- prefix. However, these two browsers do not use the Webkit engine anymore. Their engine is called Blink and is developed by Google. A basic example of a prefixed CSS property is column-gap: .column { -webkit-column-gap: 5px; -moz-column-gap: 5px; column-gap: 5px; } Knowing which CSS properties need to be prefixed is futile. That's why, it's important to keep a constant eye on CanIUse.com. However, it's also important to automate the prefixing process with tools such as Autoprefixer or -prefix-free, or mixins in preprocessors, and so on. However, vendor prefixing isn't in the scope of the book, so the properties we'll discuss are without any vendor prefixes. If you want to learn more about vendor prefixes, you can visit Mozilla Developer Network (MDN) at http://tiny.cc/mdn-vendor-prefixes. Let's get the CSS properties reference rolling. Animation Unlike the old days of Flash, where creating animations required third-party applications and plugins, today, we can accomplish practically the same things with a lot less overhead, better performance, and greater scalability, all through CSS only. Forget plugins and third-party software! All we need is a text editor, some imagination, and a bit of patience to wrap our heads around some of the animation concepts CSS brings to our plate. Base markup and CSS Before we dive into all the animation properties, we will use the following markup and animation structure as our base: HTML: <div class="element"></div> CSS: .element { width: 300px; height: 300px; } @keyframes fadingColors { 0% { background: red; } 100% { background: black; } } In the examples, we will only see the element rule since the HTML and @keyframes fadingColors will remain the same. The @keyframes declaration block is a custom animation that can be applied to any element. When applied, the element's background will go from red to black. Ok, let's do this. animation-name The animation-name CSS property is the name of the @keyframes at-rule that we want to execute, and it looks like this: animation-name: fadingColors; Description In the HTML and CSS base example, our @keyframes at-rule had an animation where the background color went from red to black. The name of that animation is fadingColors. So, we can call the animation like this: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; } This is a valid rule using the longhand. There are clearly no issues with it at all. The thing is that the animation won't run unless we add animation-duration to it. animation-duration The animation-duration CSS property defines the amount of time the animation will take to complete a cycle, and it looks like this: animation-duration: 2s; Description We can specify the units either in seconds using s or in milliseconds using ms. Specifying a unit is required. Specifying a value of 0s means that the animation should actually never run. However, since we do want our animation to run, we will use the following lines of code: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; } As mentioned earlier, this will make a box go from its red background to black in 2 seconds, and then stop. animation-iteration-count The animation-iteration-count CSS property defines the number of times the animation should be played, and it looks like this: animation-iteration-count: infinite;Description Here are two values: infinite and a number, such as 1, 3, or 0.5. Negative numbers are not allowed. Add the following code to the prior example: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; } This will make a box go from its red background to black, start over again with the red background and go to black, infinitely. animation-direction The animation-direction CSS property defines the direction in which the animation should play after the cycle, and it looks like this: animation-direction: alternate; Description There are four values: normal, reverse, alternate, and alternate-reverse. normal: It makes the animation play forward. This is the default value. reverse: It makes the animation play backward. alternate: It makes the animation play forward in the first cycle, then backward in the next cycle, then forward again, and so on. In addition, timing functions are affected, so if we have ease-out, it gets replaced by ease-in when played in reverse. We'll look at these timing functions in a minute. alternate-reverse: It's the same thing as alternate, but the animation starts backward, from the end. In our current example, we have a continuous animation. However, the background color has a "hard stop" when going from black (end of the animation) to red (start of the animation). Let's create a more 'fluid' animation by making the black background fade into red and then red into black without any hard stops. Basically, we are trying to create a "pulse-like" effect: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; } animation-delay The animation-delay CSS property allows us to define when exactly an animation should start. This means that as soon as the animation has been applied to an element, it will obey the delay before it starts running. It looks like this: animation-delay: 3s; Description We can specify the units either in seconds using s or in milliseconds using ms.Specifying a unit is required. Negative values are allowed. Take into consideration that using negative values means that the animation should start right away, but it will start midway into the animation for the opposite amount of time as the negative value. Use negative values with caution. CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; } This will make the animation start after 3 seconds have passed. animation-fill-mode The animation-fill-mode CSS property defines which values are applied to an element before and after the animation. Basically, outside the time, the animation is being executed. It looks like this: animation-fill-mode: none; Description There are four values: none, forwards, backwards, and both. none: No styles are applied before or after the animation. forwards: The animated element will retain the styles of the last keyframe. This the most used value. backwards: The animated element will retain the styles of the first keyframe, and these styles will remain during the animation-delay period. This is very likely the least used value. both: The animated element will retain the styles of the first keyframe before starting the animation and the styles of the last keyframe after the animation has finished. In many cases, this is almost the same as using forwards. The prior properties are better used in animations that have an end and stop. In our example, we're using a fading/pulsating animation, so the best property to use is none. CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; } animation-play-state The animation-play-state CSS property defines whether an animation is running or paused, and it looks like this: animation-play-state: running; Description There are two values: running and paused. These values are self-explanatory. CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; } In this case, defining animation-play-state as running is redundant, but I'm listing it for purposes of the example. animation-timing-function The animation-timing-function CSS property defines how an animation's speed should progress throughout its cycles, and it looks like this: animation-timing-function: ease-out; There are five predefined values, also known as easing functions, for the Bézier curve (we'll see what the Bézier curve is in a minute): ease, ease-in, ease-out, ease-in-out, and linear. ease The ease function Sharply accelerates at the beginning and starts slowing down towards the middle of the cycle, its syntax is as follows: animation-timing-function: ease; ease-in The ease-in function starts slowly accelerating until the animation sharply ends, its syntax is as follows: animation-timing-function: ease-in; ease-out The ease-out function starts quickly and gradually slows down towards the end: animation-timing-function: ease-out; ease-in-out The ease-in-out function starts slowly and it gets fast in the middle of the cycle. It then starts slowing down towards the end, its syntax is as follows: animation-timing-function:ease-in-out; linear The linear function has constant speed. No accelerations of any kind happen, its syntax is as follows: animation-timing-function: linear; Now, the easing functions are built on a curve named the Bézier curve and can be called using the cubic-bezier() function or the steps() function. cubic-bezier() The cubic-bezier() function allows us to create custom acceleration curves. Most use cases can benefit from the already defined easing functions we just mentioned (ease, ease-in, ease-out, ease-in-out and linear), but if you're feeling adventurous, cubic-bezier() is your best bet. Here's how a Bézier curve looks like: Parameters The cubic-bezier() function takes four parameters as follows: animation-timing-function: cubic-bezier(x1, y1, x2, y2); X and Y represent the x and y axes. The numbers 1 and 2 after each axis represent the control points. 1 represents the control point starting on the lower left, and 2 represent the control point on the upper right. Description Let's represent all five predefined easing functions with the cubic-bezier() function: ease: animation-timing-function: cubic-bezier(.25, .1, .25, 1); ease-in: animation-timing-function: cubic-bezier(.42, 0, 1, 1); ease-out: animation-timing-function: cubic-bezier(0, 0, .58, 1); ease-in-out: animation-timing-function: cubic-bezier(.42, 0, .58, 1); linear: animation-timing-function: cubic-bezier(0, 0, 1, 1); Not sure about you, but I prefer to use the predefined values. Now, we can start tweaking and testing each value to the decimal, save it, and wait for the live refresh to do its thing. However, that's too much time wasted testing if you ask me. The amazing Lea Verou created the best web app to work with Bézier curves. You can find it at cubic-bezier.com. This is by far the easiest way to work with Bézier curves. I highly recommend this tool. The Bézier curve image showed earlier was taken from the cubic-bezier.com website. Let's add animation-timing-function to our example: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; animation-timing-function: ease-out; } steps() The steps() timing function isn't very widely used, but knowing how it works is a must if you're into CSS animations. It looks like this: animation-timing-function: steps(6); This function is very helpful when we want our animation to take a defined number of steps. After adding a steps() function to our current example, it looks like this: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; animation-timing-function: steps(6); } This makes the box take six steps to fade from red to black and vice versa. Parameters There are two optional parameters that we can use with the steps() function: start and end. start: This will make the animation run at the beginning of each step. This will make the animation start right away. end: This will make the animation run at the end of each step. This is the default value if nothing is declared. This will make the animation have a short delay before it starts. Description After adding the parameters to the CSS code, it looks like this: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; animation-timing-function: steps(6, start); } Granted, in our example, is not very noticeable. However, you can see it more clear in this pen form Louis Lazarus when hovering over the boxes, at http://tiny.cc/steps-timing-function. Here's an image taken from Stephen Greig's article on Smashing Magazine, Understanding CSS Timing Functions, that explains start and end from the steps() function: Also, there are two predefined values for the steps() function: step-start and step-end. step-start: Is the same thing as steps(1, start). It means that every change happens at the beginning of each interval. step-end: Is the same thing as steps(1, end). It means that every change happens at the end of each interval. CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; animation-timing-function: step-end; } animation The animation CSS property is the shorthand for animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, and animation-play-state. It looks like this: animation: fadingColors 2s; Description For a simple animation to work, we need at least two properties: name and duration. If you feel overwhelmed by all these properties, relax. Let me break them down for you in simple bits. Using the animation longhand, the code would look like this: CSS: .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; } Using the animation shorthand, which is the recommended syntax, the code would look like this: CSS: .element { width: 300px; height: 300px; animation: fadingColors 2s; } This will make a box go from its red background to black in 2 seconds, and then stop. Final CSS code Let's see how all the animation properties look in one final example showing both the longhand and shorthand styles. Longhand style .element { width: 300px; height: 300px; animation-name: fadingColors; animation-duration: 2s; animation-iteration-count: infinite; animation-direction: alternate; animation-delay: 3s; animation-fill-mode: none; animation-play-state: running; animation-timing-function: ease-out; } Shorthand style .element { width: 300px; height: 300px; animation: fadingColors 2s infinite alternate 3s none running ease-out; } The animation-duration property will always be considered first rather than animation-delay. All other properties can appear in any order within the declaration. You can find a demo in CodePen at http://tiny.cc/animation. Summary In this article we learned how to add animations in our web project, also we learned about different properties, in detail, that can be used to animate our web project along with their description. Resources for Article: Further resources on this subject: Using JavaScript with HTML[article] Welcome to JavaScript in the full stack[article] A Typical JavaScript Project[article]
Read more
  • 0
  • 0
  • 3239

article-image-monitoring-weblogic-server-12c
Packt
21 Jun 2013
6 min read
Save for later

Monitoring WebLogic Server 12c

Packt
21 Jun 2013
6 min read
(For more resources related to this topic, see here.) Customizing the Administration Console tables The Administration Console is the central tool for managing, configuring, and monitoring WebLogic. This recipe shows how to customize the Administration Console tables to display more columns and more information and data that are hidden by default. This is a simple but essential feature to help monitor the WebLogic Server. Getting ready Access the Administration Console. The following procedure customizes the threads' monitoring table of the Managed Server Self-Tuning's thread pool. How to do it... Carry out the following steps to customize the Administration Console tables: Access the Administration Console with your web browser at http://adminhost.domain.local:7001/console. Click on the plus sign to open the Environment tree on the left and then click on the Servers link. Click on any server, such as the PROD_Server01 link. Click on the Monitoring tab and then on the Threads tab to open the Threads page. Click on the second Customize this table link of the Self-Tuning Thread Pool Threads table. Click on the >> button to add the columns Application, Module, and Work Manager. Change the Number of rows displayed per page value to 1000. Click on the Apply button. How it works... The Administration Console allows the user to customize and add more columns to the monitoring tables. In this recipe, the Application, Module, and Work Manager columns are added to the Self-Tuning Thread Pool Threads table. The added columns are very useful to monitor the application requests being processed. The following table displays thread 0 processing a request of the testWeb application and thread 1 processing a request of the myApp application. Customizing the Administration Console monitoring tables is a common task and can be applied in a variety of tables, such as the data sources, the JMS queues, and transactions. Using the JRockit Mission Control Management Console Mission Control is a monitoring and troubleshooting application provided with Oracle JRockit. From a monitoring point of view, Mission Control provides a Management Console to monitor the garbage-collection behavior, processor utilization by the JVM, memory allocation, thread utilization, and some other useful monitoring metrics. Mission Control is a standalone application, so it must be started either locally from the same machine that WebLogic is running on or from a remote workstation. If you run Mission Control locally on the Linux server prod01, an X window must be available. This recipe will run Mission Control in a Microsoft Windows desktop and will remotely connect and monitor the PROD_Server01 Managed Server. Getting ready Oracle JRockit must be downloaded and installed in the Windows desktop. Download Oracle JRockit 6 for Microsoft Windows at http://www.oracle.com/technetwork/ middleware/jrockit/downloads. The filename is jrockit-jdk1.6.0_XXX-windowsiaYY. exe, where XXX stands for the JRockit release and JDK version and YY stands for 32 bits or 64 bits. Choose the version that matches your desktop and accept the license agreement to download it. How to do it... Enable the PROD_Server01 Managed Server to accept JMX connections from Mission Control: Access the Administration Console with your web browser at http://adminhost.domain.local:7001/console. Click on the Lock & Edit button to start a new edit session. Click on the plus sign to open the Environment tree on the left and then click Servers. Click on the PROD_Server01 link and then click the Server Start tab. Add the following to the Arguments field and click on the Save button: -Xmanagement:autodiscovery=false,authenticate=false,ssl=false,interface=prodsrv01.domain.local,port=8081 -Djava.rmi.server.hostname=prodsrv01.domain.local -Djavax.management.builder.initial=weblogic.management.jmx.mbeanserver.WLSMBeanServerBuilder Click on the Activate Changes button. Restart PROD_Server01. Start Mission Control on the desktop, as follows: Start Mission Control by double-clicking on the Oracle JRockit Mission Control icon. On the JVM Browser panel to the left, right-click on the Connectors folder and click on the New Connection option. Type prodsrv01.domain.local in the Host field and 8081 in the Port field and click on the Finish button. Right-click on the newly created connection, prodsrv01.domain.local:8081, and click on the Start Console menu option. How it works... Mission Control connects to the specified host and port defined in the Xmanagement start-up argument and starts monitoring the PROD_Server01 JVM. Add the start-up arguments to monitor the other WebLogic instances. Mission Control can connect to any running JRockit JVM. Monitoring Linux with SAR A Linux host with Red Hat Enterprise Linux or Oracle Linux can be monitored using the SAR command-line utility. The SAR is included in the SYSSTAT package bundle and is usually included with these Linux distributions. SAR retrieves activity counters of the operational system, such as CPU, memory, disk, and network I/O usage. By default, it keeps a history of seven days, so it is a very useful tool to retrieve past reports and quickly search for behavioral patterns. This recipe will retrieve some statistics from the prod01 machine using the SAR command-line utility. Getting ready SAR should already be installed in a Red Hat or Oracle Linux distribution. If it is not installed, you can use the yum package management utility to install the SYSSTAT package, which includes SAR. As root user, execute the yum command and follow the onscreen instructions to install SYSSTAT: [root@prod01]$ yum install sysstat All SAR commands are executed from the Linux shell. Log in to the host first. The root user is used only to install the SYSSTAT package. How to do it... To retrieve the queue length and load averages from the current day, as a wls user execute the following command: [wls@prod01]$ sar -q This will display the following result: To retrieve a past CPU usage from the 21st day of the month, as a wls user execute the following command: [wls@prod01]$ sar –u –f /var/log/sa/sa21 This will display the following result: The default SAR configuration keeps historical data for a week. How it works... The SAR utility is very flexible and provides a quick way to watch the host behavior for the current day and for the past seven days. SAR runs every 10 minutes and saves a summary at the end of the day. These are the default values in the crontab and can be adjusted. There's more... Apart from the options discussed earlier, we can view more fine-grained data as well. Collecting SAR data every minute SAR can store statistical data in a more fine-grained time interval. Log in as a root user to the shell and execute the following command: [root@prod01]$ vi /etc/cron.d/sysstat Locate the following lines: # run system activity accounting tool every 10 minutes*/10 * * * * root /usr/lib64/sa/sa1 1 1 Change these lines to the following: # run system activity accounting tool every 1 minute*/1 * * * * root /usr/lib64/sa/sa1 1 1 Type :wq! to save and close the file.
Read more
  • 0
  • 0
  • 3239

article-image-machine-learning-practice
Packt
18 Feb 2016
13 min read
Save for later

Machine learning in practice

Packt
18 Feb 2016
13 min read
In this article, we will learn how we can implement machine learning in practice. To apply the learning process to real-world tasks, we'll use a five-step process. Regardless of the task at hand, any machine learning algorithm can be deployed by following this plan: Data collection: The data collection step involves gathering the learning material an algorithm will use to generate actionable knowledge. In most cases, the data will need to be combined into a single source like a text file, spreadsheet, or database. Data exploration and and preparation: The quality of any machine learning project is based largely on the quality of its input data. Thus, it is important to learn more about the data and its nuances during a practice called data exploration. Additional work is required to prepare the data for the learning process. This involves fixing or cleaning so-called "messy" data, eliminating unnecessary data, and recoding the data to conform to the learner's expected inputs. Model training: By the time the data has been prepared for analysis, you are likely to have a sense of what you are capable of learning from the data. The specific machine learning task chosen will inform the selection of an appropriate algorithm and the algorithm will represent the data in the form of a model. Model evaluation: Because each machine learning model results in a biased solution to the learning problem, it is important to evaluate how well the algorithm learns from its experience. Depending on the type of model used, you might be able to evaluate the accuracy of the model using a test dataset or you may need to develop measures of performance specific to the intended application. Model improvement: If better performance is needed, it becomes necessary to utilize more advanced strategies to augment the performance of the model. Sometimes, it may be necessary to switch to a different type of model altogether. You may need to supplement your data with additional data or perform additional preparatory work as in step two of this process. (For more resources related to this topic, see here.) After these steps are completed, if the model appears to be performing well, it can be deployed for its intended task. As the case may be, you might utilize your model to provide score data for predictions (possibly in real time), for projections of financial data, to generate useful insight for marketing or research, or to automate tasks such as mail delivery or flying aircraft. The successes and failures of the deployed model might even provide additional data to train your next generation learner. Types of input data The practice of machine learning involves matching the characteristics of input data to the biases of the available approaches. Thus, before applying machine learning to real-world problems, it is important to understand the terminology that distinguishes among input datasets. The phrase unit of observation is used to describe the smallest entity with measured properties of interest for a study. Commonly, the unit of observation is in the form of persons, objects or things, transactions, time points, geographic regions, or measurements. Sometimes, units of observation are combined to form units such as person-years, which denote cases where the same person is tracked over multiple years; each person-year comprises of a person's data for one year. The unit of observation is related but not identical to the unit of analysis, which is the smallest unit from which the inference is made. Although it is often the case, the observed and analyzed units are not always the same. For example, data observed from people might be used to analyze trends across countries. Datasets that store the units of observation and their properties can be imagined as collections of data consisting of: Examples: Instances of the unit of observation for which properties have been recorded Features: Recorded properties or attributes of examples that may be useful for learning It is the easiest to understand features and examples through real-world cases. To build a learning algorithm to identify spam e-mail, the unit of observation could be e-mail messages, examples would be specific messages, and its features might consist of the words used in the messages. For a cancer detection algorithm, the unit of observation could be patients, the examples might include a random sample of cancer patients, and its features may be the genomic markers from biopsied cells as well as the characteristics of patient such as weight, height, or blood pressure. While examples and features do not have to be collected in any specific form, they are commonly gathered in the matrix format, which means that each example has exactly the same features. The following spreadsheet shows a dataset in the matrix format. In the matrix data, each row in the spreadsheet is an example and each column is a feature. Here, the rows indicate examples of automobiles, while the columns record various each automobile's feature, such as price, mileage, color, and transmission type. Matrix format data is by far the most common form used in machine learning, though other forms are used occasionally in specialized cases: Features also come in various forms. If a feature represents a characteristic measured in numbers, it is unsurprisingly called numeric. Alternatively, if a feature is an attribute that consists of a set of categories, the feature is called categorical or nominal. A special case of categorical variables is called ordinal, which designates a nominal variable to the categories falling in an ordered list. Some examples of ordinal variables include clothing sizes such as small, medium, and large, or a measurement of customer satisfaction on a scale from "not at all happy" to "very happy." It is important to consider what the features represent, as the type and number of features in your dataset will assist in determining an appropriate machine learning algorithm for your task. Types of machine learning algorithms Machine learning algorithms are divided into categories according to their purpose. Understanding the categories of learning algorithms is an essential first step towards using data to drive the desired action. A predictive model is used for tasks that involve, as the name implies, the prediction of one value using other values in the dataset. The learning algorithm attempts to discover and model the relationship between the target feature (the feature being predicted) and the other features. Despite the common use of the word "prediction" to imply forecasting, predictive models need not necessarily foresee events in the future. For instance, a predictive model could be used to predict past events such as the date of a baby's conception using the mother's present-day hormone levels. Predictive models can also be used in real time to control traffic lights during rush hours. Because predictive models are given clear instruction on what they need to learn and how they are intended to learn it, the process of training a predictive model is known as supervised learning. The supervision does not refer to human involvement, but rather to the fact that the target values provide a way for the learner to know how well it has learned the desired task. Stated more formally, given a set of data, a supervised learning algorithm attempts to optimize a function (the model) to find the combination of feature values that result in the target output. The often used supervised machine learning task of predicting which category an example belongs to is known as classification. It is easy to think of potential uses for a classifier. For instance, you could predict whether: An e-mail message is spam A person has cancer A football team will win or lose An applicant will default on a loan In classification, the target feature to be predicted is a categorical feature known as the class and is divided into categories called levels. A class can have two or more levels, and the levels may or may not be ordinal. Because classification is so widely used in machine learning, there are many types of classification algorithms, with strengths and weaknesses suited for different types of input data. Supervised learners can also be used to predict numeric data such as income, laboratory values, test scores, or counts of items. To predict such numeric values, a common form of numeric prediction fits linear regression models to the input data. Although regression models are not the only type of numeric models, they are, by far, the most widely used. Regression methods are widely used for forecasting, as they quantify in exact terms the association between inputs and the target, including both, the magnitude and uncertainty of the relationship. Since it is easy to convert numbers into categories (for example, ages 13 to 19 are teenagers) and categories into numbers (for example, assign 1 to all males, 0 to all females), the boundary between classification models and numeric prediction models is not necessarily firm. A descriptive model is used for tasks that would benefit from the insight gained from summarizing data in new and interesting ways. As opposed to predictive models that predict a target of interest, in a descriptive model, no single feature is more important than the other. In fact, because there is no target to learn, the process of training a descriptive model is called unsupervised learning. Although it can be more difficult to think of applications for descriptive models—after all, what good is a learner that isn't learning anything in particular—they are used quite regularly for data mining. For example, the descriptive modeling task called pattern discovery is used to identify useful associations within data. Pattern discovery is often used for market basket analysis on retailers' transactional purchase data. Here, the goal is to identify items that are frequently purchased together, such that the learned information can be used to refine marketing tactics. For instance, if a retailer learns that swimming trunks are commonly purchased at the same time as sunscreens, the retailer might reposition the items more closely in the store or run a promotion to "up-sell" customers on associated items. Originally used only in retail contexts, pattern discovery is now starting to be used in quite innovative ways. For instance, it can be used to detect patterns of fraudulent behavior, screen for genetic defects, or identify hot spots for criminal activity. The descriptive modeling task of dividing a dataset into homogeneous groups is called clustering. This is, sometimes, used for segmentation analysis that identifies groups of individuals with similar behavior or demographic information so that advertising campaigns could be tailored for particular audiences. Although the machine is capable of identifying the clusters, human intervention is required to interpret them. For example, given five different clusters of shoppers at a grocery store, the marketing team will need to understand the differences among the groups in order to create a promotion that best suits each group. This is almost certainly easier than trying to create a unique appeal for each customer. Lastly, a class of machine learning algorithms known as meta-learners is not tied to a specific learning task, but is rather focused on learning how to learn more effectively. A meta-learning algorithm uses the result of some learnings to inform additional learning. This can be beneficial for very challenging problems or when a predictive algorithm's performance needs to be as accurate as possible. Matching input data to algorithms The following table lists the general types of machine learning algorithms, each of which may be implemented in several ways. These are the basis on which nearly all the other more advanced methods are based. Although this covers only a fraction of the entire set of machine learning algorithms, learning these methods will provide a sufficient foundation to make sense of any other method you may encounter in the future. Model Learning task Supervised Learning Algorithms Nearest Neighbor Classification Naive Bayes Classification Decision Trees Classification Classification Rule Learners Classification Linear Regression Numeric prediction Regression Trees Numeric prediction Model Trees Numeric prediction Neural Networks Dual use Support Vector Machines Dual use Unsupervised Learning Algorithms Association Rules Pattern detection k-means clustering Clustering Meta-Learning Algorithms Bagging Dual use Boosting Dual use Random Forests Dual use  To begin applying machine learning to a real-world project, you will need to determine which of the four learning tasks your project represents: classification, numeric prediction, pattern detection, or clustering. The task will drive the choice of algorithm. For instance, if you are undertaking pattern detection, you are likely to employ association rules. Similarly, a clustering problem will likely utilize the k-means algorithm and numeric prediction will utilize regression analysis or regression trees. For classification, more thought is needed to match a learning problem to an appropriate classifier. In these cases, it is helpful to consider various distinctions among algorithms—distinctions that will only be apparent by studying each of the classifiers in depth. For instance, within classification problems, decision trees result in models that are readily understood, while the models of neural networks are notoriously difficult to interpret. If you were designing a credit-scoring model, this could be an important distinction because law often requires that the applicant must be notified about the reasons he or she was rejected for the loan. Even if the neural network is better at predicting loan defaults, if its predictions cannot be explained, then it is useless for this application. Although you will sometimes find that these characteristics exclude certain models from consideration. In many cases, the choice of algorithm is arbitrary. When this is true, feel free to use whichever algorithm you are most comfortable with. Other times, when predictive accuracy is primary, you may need to test several algorithms and choose the one that fits the best or use a meta-learning algorithm that combines several different learners to utilize the strengths of each. Summary Machine learning originated at the intersection of statistics, database science, and computer science. It is a powerful tool, capable of finding actionable insight in large quantities of data. Still, caution must be used in order to avoid common abuses of machine learning in the real world. Conceptually, learning involves the abstraction of data into a structured representation and the generalization of this structure into action that can be evaluated for utility. In practical terms, a machine learner uses data containing examples and features of the concept to be learned and summarizes this data in the form of a model, which is then used for predictive or descriptive purposes. These purposes can be grouped into tasks, including classification, numeric prediction, pattern detection, and clustering. Among the many options, machine learning algorithms are chosen on the basis of the input data and the learning task. R provides support for machine learning in the form of community-authored packages. These powerful tools are free to download, but need to be installed before they can be used. Resources for Article:   Further resources on this subject: Introduction to Machine Learning with R [article] Machine Learning with R [article] Spark – Architecture and First Program [article]
Read more
  • 0
  • 0
  • 3238
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-machine-learning-ipython-scikit-learn-0
Packt
25 Sep 2014
13 min read
Save for later

Machine Learning in IPython with scikit-learn

Packt
25 Sep 2014
13 min read
This article written by Daniele Teti, the author of Ipython Interactive Computing and Visualization Cookbook, the basics of the machine learning scikit-learn package (http://scikit-learn.org) is introduced. Its clean API makes it really easy to define, train, and test models. Plus, scikit-learn is specifically designed for speed and (relatively) big data. (For more resources related to this topic, see here.) A very basic example of linear regression in the context of curve fitting is shown here. This toy example will allow to illustrate key concepts such as linear models, overfitting, underfitting, regularization, and cross-validation. Getting ready You can find all instructions to install scikit-learn on the main documentation. For more information, refer to http://scikit-learn.org/stable/install.html. With anaconda, you can type conda install scikit-learn in a terminal. How to do it... We will generate a one-dimensional dataset with a simple model (including some noise), and we will try to fit a function to this data. With this function, we can predict values on new data points. This is a curve fitting regression problem. First, let's make all the necessary imports: In [1]: import numpy as np        import scipy.stats as st        import sklearn.linear_model as lm        import matplotlib.pyplot as plt        %matplotlib inline We now define a deterministic nonlinear function underlying our generative model: In [2]: f = lambda x: np.exp(3 * x) We generate the values along the curve on [0,2]: In [3]: x_tr = np.linspace(0., 2, 200)        y_tr = f(x_tr) Now, let's generate data points within [0,1]. We use the function f and we add some Gaussian noise: In [4]: x = np.array([0, .1, .2, .5, .8, .9, 1])        y = f(x) + np.random.randn(len(x)) Let's plot our data points on [0,1]: In [5]: plt.plot(x_tr[:100], y_tr[:100], '--k')        plt.plot(x, y, 'ok', ms=10) In the image, the dotted curve represents the generative model. Now, we use scikit-learn to fit a linear model to the data. There are three steps. First, we create the model (an instance of the LinearRegression class). Then, we fit the model to our data. Finally, we predict values from our trained model. In [6]: # We create the model.        lr = lm.LinearRegression()        # We train the model on our training dataset.        lr.fit(x[:, np.newaxis], y)        # Now, we predict points with our trained model.        y_lr = lr.predict(x_tr[:, np.newaxis]) We need to convert x and x_tr to column vectors, as it is a general convention in scikit-learn that observations are rows, while features are columns. Here, we have seven observations with one feature. We now plot the result of the trained linear model. We obtain a regression line in green here: In [7]: plt.plot(x_tr, y_tr, '--k')        plt.plot(x_tr, y_lr, 'g')        plt.plot(x, y, 'ok', ms=10)        plt.xlim(0, 1)        plt.ylim(y.min()-1, y.max()+1)        plt.title("Linear regression") The linear fit is not well-adapted here, as the data points are generated according to a nonlinear model (an exponential curve). Therefore, we are now going to fit a nonlinear model. More precisely, we will fit a polynomial function to our data points. We can still use linear regression for this, by precomputing the exponents of our data points. This is done by generating a Vandermonde matrix, using the np.vander function. We will explain this trick in How it works…. In the following code, we perform and plot the fit: In [8]: lrp = lm.LinearRegression()        plt.plot(x_tr, y_tr, '--k')        for deg in [2, 5]:            lrp.fit(np.vander(x, deg + 1), y)            y_lrp = lrp.predict(np.vander(x_tr, deg + 1))            plt.plot(x_tr, y_lrp,                      label='degree ' + str(deg))             plt.legend(loc=2)            plt.xlim(0, 1.4)            plt.ylim(-10, 40)            # Print the model's coefficients.            print(' '.join(['%.2f' % c for c in                            lrp.coef_]))        plt.plot(x, y, 'ok', ms=10)      plt.title("Linear regression") 25.00 -8.57 0.00 -132.71 296.80 -211.76 72.80 -8.68 0.00 We have fitted two polynomial models of degree 2 and 5. The degree 2 polynomial appears to fit the data points less precisely than the degree 5 polynomial. However, it seems more robust; the degree 5 polynomial seems really bad at predicting values outside the data points (look for example at the x 1 portion). This is what we call overfitting; by using a too complex model, we obtain a better fit on the trained dataset, but a less robust model outside this set. Note the large coefficients of the degree 5 polynomial; this is generally a sign of overfitting. We will now use a different learning model, called ridge regression. It works like linear regression except that it prevents the polynomial's coefficients from becoming too big. This is what happened in the previous example. By adding a regularization term in the loss function, ridge regression imposes some structure on the underlying model. We will see more details in the next section. The ridge regression model has a meta-parameter, which represents the weight of the regularization term. We could try different values with trials and errors, using the Ridge class. However, scikit-learn includes another model called RidgeCV, which includes a parameter search with cross-validation. In practice, it means that we don't have to tweak this parameter by hand—scikit-learn does it for us. As the models of scikit-learn always follow the fit-predict API, all we have to do is replace lm.LinearRegression() by lm.RidgeCV() in the previous code. We will give more details in the next section. In [9]: ridge = lm.RidgeCV()        plt.plot(x_tr, y_tr, '--k')               for deg in [2, 5]:             ridge.fit(np.vander(x, deg + 1), y);            y_ridge = ridge.predict(np.vander(x_tr, deg+1))            plt.plot(x_tr, y_ridge,                      label='degree ' + str(deg))            plt.legend(loc=2)            plt.xlim(0, 1.5)           plt.ylim(-5, 80)            # Print the model's coefficients.            print(' '.join(['%.2f' % c                            for c in ridge.coef_]))               plt.plot(x, y, 'ok', ms=10)        plt.title("Ridge regression") 11.36 4.61 0.00 2.84 3.54 4.09 4.14 2.67 0.00 This time, the degree 5 polynomial seems more precise than the simpler degree 2 polynomial (which now causes underfitting). Ridge regression reduces the overfitting issue here. Observe how the degree 5 polynomial's coefficients are much smaller than in the previous example. How it works... In this section, we explain all the aspects covered in this article. The scikit-learn API scikit-learn implements a clean and coherent API for supervised and unsupervised learning. Our data points should be stored in a (N,D) matrix X, where N is the number of observations and D is the number of features. In other words, each row is an observation. The first step in a machine learning task is to define what the matrix X is exactly. In a supervised learning setup, we also have a target, an N-long vector y with a scalar value for each observation. This value is continuous or discrete, depending on whether we have a regression or classification problem, respectively. In scikit-learn, models are implemented in classes that have the fit() and predict() methods. The fit() method accepts the data matrix X as input, and y as well for supervised learning models. This method trains the model on the given data. The predict() method also takes data points as input (as a (M,D) matrix). It returns the labels or transformed points as predicted by the trained model. Ordinary least squares regression Ordinary least squares regression is one of the simplest regression methods. It consists of approaching the output values yi with a linear combination of Xij: Here, w = (w1, ..., wD) is the (unknown) parameter vector. Also, represents the model's output. We want this vector to match the data points y as closely as possible. Of course, the exact equality cannot hold in general (there is always some noise and uncertainty—models are always idealizations of reality). Therefore, we want to minimize the difference between these two vectors. The ordinary least squares regression method consists of minimizing the following loss function: This sum of the components squared is called the L2 norm. It is convenient because it leads to differentiable loss functions so that gradients can be computed and common optimization procedures can be performed. Polynomial interpolation with linear regression Ordinary least squares regression fits a linear model to the data. The model is linear both in the data points Xiand in the parameters wj. In our example, we obtain a poor fit because the data points were generated according to a nonlinear generative model (an exponential function). However, we can still use the linear regression method with a model that is linear in wj, but nonlinear in xi. To do this, we need to increase the number of dimensions in our dataset by using a basis of polynomial functions. In other words, we consider the following data points: Here, D is the maximum degree. The input matrix X is therefore the Vandermonde matrix associated to the original data points xi. For more information on the Vandermonde matrix, refer to http://en.wikipedia.org/wiki/Vandermonde_matrix. Here, it is easy to see that training a linear model on these new data points is equivalent to training a polynomial model on the original data points. Ridge regression Polynomial interpolation with linear regression can lead to overfitting if the degree of the polynomials is too large. By capturing the random fluctuations (noise) instead of the general trend of the data, the model loses some of its predictive power. This corresponds to a divergence of the polynomial's coefficients wj. A solution to this problem is to prevent these coefficients from growing unboundedly. With ridge regression (also known as Tikhonov regularization) this is done by adding a regularization term to the loss function. For more details on Tikhonov regularization, refer to http://en.wikipedia.org/wiki/Tikhonov_regularization. By minimizing this loss function, we not only minimize the error between the model and the data (first term, related to the bias), but also the size of the model's coefficients (second term, related to the variance). The bias-variance trade-off is quantified by the hyperparameter , which specifies the relative weight between the two terms in the loss function. Here, ridge regression led to a polynomial with smaller coefficients, and thus a better fit. Cross-validation and grid search A drawback of the ridge regression model compared to the ordinary least squares model is the presence of an extra hyperparameter . The quality of the prediction depends on the choice of this parameter. One possibility would be to fine-tune this parameter manually, but this procedure can be tedious and can also lead to overfitting problems. To solve this problem, we can use a grid search; we loop over many possible values for , and we evaluate the performance of the model for each possible value. Then, we choose the parameter that yields the best performance. How can we assess the performance of a model with a given value? A common solution is to use cross-validation. This procedure consists of splitting the dataset into a train set and a test set. We fit the model on the train set, and we test its predictive performance on the test set. By testing the model on a different dataset than the one used for training, we reduce overfitting. There are many ways to split the initial dataset into two parts like this. One possibility is to remove one sample to form the train set and to put this one sample into the test set. This is called Leave-One-Out cross-validation. With N samples, we obtain N sets of train and test sets. The cross-validated performance is the average performance on all these set decompositions. As we will see later, scikit-learn implements several easy-to-use functions to do cross-validation and grid search. In this article, there exists a special estimator called RidgeCV that implements a cross-validation and grid search procedure that is specific to the ridge regression model. Using this model ensures that the best hyperparameter is found automatically for us. There's more… Here are a few references about least squares: Ordinary least squares on Wikipedia, available at http://en.wikipedia.org/wiki/Ordinary_least_squares Linear least squares on Wikipedia, available at http://en.wikipedia.org/wiki/Linear_least_squares_(mathematics) Here are a few references about cross-validation and grid search: Cross-validation in scikit-learn's documentation, available at http://scikit-learn.org/stable/modules/cross_validation.html Grid search in scikit-learn's documentation, available at http://scikit-learn.org/stable/modules/grid_search.html Cross-validation on Wikipedia, available at http://en.wikipedia.org/wiki/Cross-validation_%28statistics%29 Here are a few references about scikit-learn: scikit-learn basic tutorial available at http://scikit-learn.org/stable/tutorial/basic/tutorial.html scikit-learn tutorial given at the SciPy 2013 conference available at https://github.com/jakevdp/sklearn_scipy2013 Summary Using the scikit-learn Python package, this article illustrates fundamental data mining and machine learning concepts such as supervised and unsupervised learning, classification, regression, feature selection, feature extraction, overfitting, regularization, cross-validation, and grid search. Resources for Article: Further resources on this subject: Driving Visual Analyses with Automobile Data (Python) [Article] Fast Array Operations with NumPy [Article] Python 3: Designing a Tasklist Application [Article]
Read more
  • 0
  • 0
  • 3237

article-image-getting-started-spark-2-0
Sunith Shetty
28 Dec 2017
10 min read
Save for later

Getting started with Spark 2.0

Sunith Shetty
28 Dec 2017
10 min read
[box type="note" align="" class="" width=""]This article is an excerpt from a book by Muhammad Asif Abbasi titled Learning Apache Spark 2. In this book, author explains how to perform big data analytics using Spark streaming, machine learning techniques and more.[/box] Today, we will learn about the basics of Spark architecture and its various components. We will also explore how to install Spark for running it in the local mode. Apache Spark architecture overview Apache Spark is an open source distributed data processing engine for clusters, which provides a unified programming model engine across different types data processing workloads and platforms. At the core of the project is a set of APIs for Streaming, SQL, Machine Learning (ML), and Graph. Spark community supports the Spark project by providing connectors to various open source and proprietary data storage engines. Spark also has the ability to run on a variety of cluster managers like YARN and Mesos, in addition to the Standalone cluster manager which comes bundled with Spark for standalone installation. This is thus a marked difference from Hadoop ecosystem where Hadoop provides a complete platform in terms of storage formats, compute engine, cluster manager, and so on. Spark has been designed with the single goal of being an optimized compute engine. This therefore allows you to run Spark on a variety of cluster managers including being run standalone, or being plugged into YARN and Mesos. Similarly, Spark does not have its own storage, but it can connect to a wide number of storage engines. Currently Spark APIs are available in some of the most common languages including Scala, Java, Python, and R. Let's start by going through various API's available in Spark. Spark-core At the heart of the Spark architecture is the core engine of Spark, commonly referred to as spark-core, which forms the foundation of this powerful architecture. Spark-core provides services such as managing the memory pool, scheduling of tasks on the cluster (Spark works as a Massively Parallel Processing (MPP) system when deployed in cluster mode), recovering failed jobs, and providing support to work with a wide variety of storage systems such as HDFS, S3, and so on. Note: Spark-Core provides a full scheduling component for Standalone Scheduling: Code is available at: https://github.com/apache/spark/tree/master/core/src/main/scala/org/apache/spark/scheduler Spark-Core abstracts the users of the APIs from lower-level technicalities of working on a cluster. Spark-Core also provides the RDD APIs which are the basis of other higher-level APIs, and are the core programming elements on Spark. Note: MPP systems generally use a large number of processors (on separate hardware or virtualized) to perform a set of operations in parallel. The objective of the MPP systems is to divide work into smaller task pieces and running them in parallel to increase in throughput time. Spark SQL Spark SQL is one of the most popular modules of Spark designed for structured and semistructured data processing. Spark SQL allows users to query structured data inside Spark programs using SQL or the DataFrame and the Dataset API, which is usable in Java, Scala, Python, and R. Because of the fact that the DataFrame API provides a uniform way to access a variety of data sources, including Hive datasets, Avro, Parquet, ORC, JSON, and JDBC, users should be able to connect to any data source the same way, and join across these multiple sources together. The usage of Hive meta store by Spark SQL gives the user full compatibility with existing Hive data, queries, and UDFs. Users can seamlessly run their current Hive workload without modification on Spark. Spark SQL can also be accessed through spark-sql shell, and existing business tools can connect via standard JDBC and ODBC interfaces. Spark streaming More than 50% of users consider Spark Streaming to be the most important component of Apache Spark. Spark Streaming is a module of Spark that enables processing of data arriving in passive or live streams of data. Passive streams can be from static files that you choose to stream to your Spark cluster. This can include all sorts of data ranging from web server logs, social-media activity (following a particular Twitter hashtag), sensor data from your car/phone/home, and so on. Spark-streaming provides a bunch of APIs that help you to create streaming applications in a way similar to how you would create a batch job, with minor tweaks. As of Spark 2.0, the philosophy behind Spark Streaming is not to reason about streaming and building data application as in the case of a traditional data source. This means the data from sources is continuously appended to the existing tables, and all the operations are run on the new window. A single API lets the users create batch or streaming applications, with the only difference being that a table in batch applications is finite, while the table for a streaming job is considered to be infinite. MLlib MLlib is Machine Learning Library for Spark, if you remember from the preface, iterative algorithms are one of the key drivers behind the creation of Spark, and most machine learning algorithms perform iterative processing in one way or another. Note: Machine learning is a type of artificial intelligence (AI) that provides computers with the ability to learn without being explicitly programmed. Machine learning focuses on the development of computer programs that can teach themselves to grow and change when exposed to new data. Spark MLlib allows developers to use Spark API and build machine learning algorithms by tapping into a number of data sources including HDFS, HBase, Cassandra, and so on. Spark is super fast with iterative computing and it performs 100 times better than MapReduce. Spark MLlib contains a number of algorithms and utilities including, but not limited to, logistic regression, Support Vector Machine (SVM), classification and regression trees, random forest and gradient-boosted trees, recommendation via ALS, clustering via K-Means, Principal Component Analysis (PCA), and many others. GraphX GraphX is an API designed to manipulate graphs. The graphs can range from a graph of web pages linked to each other via hyperlinks to a social network graph on Twitter connected by followers or retweets, or a Facebook friends list. Graph theory is a study of graphs, which are mathematical structures used to model pairwise relations between objects. A graph is made up of vertices (nodes/points), which are connected by edges (arcs/lines).                                                                                                                            – Wikipedia.org Spark provides a built-in library for graph manipulation, which therefore allows the developers to seamlessly work with both graphs and collections by combining ETL, discovery analysis, and iterative graph manipulation in a single workflow. The ability to combine transformations, machine learning, and graph computation in a single system at high speed makes Spark one of the most flexible and powerful frameworks out there. The ability of Spark to retain the speed of computation with the standard features of fault-tolerance makes it especially handy for big data problems. Spark GraphX has a number of built-in graph algorithms including PageRank, Connected components, Label propagation, SVD++, and Triangle counter. Spark deployment Apache Spark runs on both Windows and Unix-like systems (for example, Linux and Mac OS). If you are starting with Spark you can run it locally on a single machine. Spark requires Java 7+, Python 2.6+, and R 3.1+. If you would like to use Scala API (the language in which Spark was written), you need at least Scala version 2.10.x. Spark can also run in a clustered mode, using which Spark can run both by itself, and on several existing cluster managers. You can deploy Spark on any of the following cluster managers, and the list is growing everyday due to active community support: Hadoop YARN. Apache Mesos. Standalone scheduler. Yet Another Resource Negotiator (YARN) is one of the key features including a redesigned resource manager thus splitting out the scheduling and resource management capabilities from original MapReduce in Hadoop. Apache Mesos is an open source cluster manager that was developed at the University of California, Berkeley. It provides efficient resource isolation and sharing across distributed applications, or frameworks. Installing Apache Spark As mentioned in the earlier pages, while Spark can be deployed on a cluster, you can also run it in local mode on a single machine. In this chapter, we are going to download and install Apache Spark on a Linux machine and run it in local mode. Before we do anything we need to download Apache Spark from Apache's web page for the Spark project: Use your recommended browser to navigate to http://spark.apache.org/downloads.html. Choose a Spark release. You'll find all previous Spark releases listed here. We'll go with release 2.0.0 (at the time of writing, only the preview edition was available). You can download Spark source code, which can be built for several versions of Hadoop, or download it for a specific Hadoop version. In this case, we are going to download one that has been pre-built for Hadoop 2.7 or later. You can also choose to download directly or from among a number of different Mirrors. For the purpose of our exercise we'll use direct download and download it to our preferred location. Note: If you are using Windows, please remember to use a pathname without any spaces. 5. The file that you have downloaded is a compressed TAR archive. You need to extract the archive. Note: The TAR utility is generally used to unpack TAR files. If you don't have TAR, you might want to download that from the repository or use 7-ZIP, which is also one of my favorite utilities. 6. Once unpacked, you will see a number of directories/files. Here's what you would typically see when you list the contents of the unpacked directory: The bin folder contains a number of executable shell scripts such as pypark, sparkR, spark-shell, spark-sql, and spark-submit. All of these executables are used to interact with Spark, and we will be using most if not all of these. 7. If you see my particular download of spark you will find a folder called yarn. The example below is a Spark that was built for Hadoop version 2.7 which comes with YARN as a cluster manager. We'll start by running Spark shell, which is a very simple way to get started with Spark and learn the API. Spark shell is a Scala Read-Evaluate-Print-Loop (REPL), and one of the few REPLs available with Spark which also include Python and R. You should change to the Spark download directory and run the Spark shell as follows: /bin/spark-shell. We now have Spark running in standalone mode. We'll discuss the details of the deployment architecture a bit later in this chapter, but now let's kick start some basic Spark programming to appreciate the power and simplicity of the Spark framework. We have gone through the Spark architecture overview and the steps to install Spark on your own personal machine. To know more about Spark SQL, Spark Streaming, and Machine Learning with Spark, you can refer our book Learning Apache Spark 2.    
Read more
  • 0
  • 0
  • 3236

article-image-sencha-touch-layouts-revisited
Packt
16 Feb 2012
7 min read
Save for later

Sencha Touch: Layouts Revisited

Packt
16 Feb 2012
7 min read
  (For more resources on this topic, see here.) The reader can benefit from the previous article on The Various Components in Sencha Touch. The base component class When we talk about components in Sencha Touch, we are generally talking about buttons, panels, sliders, toolbars, form fields, and other tangible items that we can see on the screen. However, all of these components inherit their configuration options, methods, properties, and events from a single base component with the startlingly original name of component. This can obviously lead to a bit of confusion, so we will refer to this as Ext.Component. One of the most important things to understand is that you will never actually use Ext.Component directly. It is simply used as a building block for all of the other components in Sencha Touch. However, it is important to be familiar with the base component class, because anything it can do, all the other components can do. Learning this one class can give you a huge head start on everything else. Some of the more useful configuration options of Ext.Component are as follows: border cls disabled height/width hidden html margin padding scroll style ui Ext.Component also contains a number of useful methods that will allow you to get and set properties on any Sencha Touch component. Here are a few of those methods: addCls and removeCls: Add or remove a CSS class from your component. destroy: Remove the component from memory. disable and enable: Disable or enable the component (very useful in forms). getHeight, getWidth, and getSize: Get the current height, width, or size of the component. Size returns both height and width. You can also use setHeight, setWidth, and setSize, to change the dimensions of your component. show and hide: Show or hide the component. setPosition: Set the top and left values for the component. update: Update the content area of a component. Unlike our configuration options, methods can only be used once the component is created. This means we also need to understand how to get the component itself before we can begin using the methods. This is where the Ext class comes into play. The Ext object and Ext.getCmp() The Ext object is created, by default, when the Sencha Touch library is loaded. This object has methods that are used to create our initial application and its components. It also allows us to talk to our other components after they have been created. For example, let's take a look at a code example: new Ext.Application({ name: 'TouchStart', launch: function() { var hello = new Ext.Container({ fullscreen: true, html: '<div id="hello">Hello World</div>', id: 'helloContainer' }); this.viewport = hello;}}); The configuration option, id: 'helloContainer' will allow us to grab the container, later on, using our Ext class and the method getCmp(). For example, we can add the following code after this.viewport = hello;: var myContainer = Ext.getCmp('helloContainer');myContainer.update('Hello Again!'); By using Ext.getCmp, we get back the component with an id value of helloContainer, which we then set to our variable myContainer. Using this method returns an actual component, in this case a container. Since we get this object back as a container component, we can use any of the methods that the container understands. For our example, we used the update() method to change the content of the container to 'Hello Again!'. Typically, these types of changes will be generated by a button click and not in the launch function. This example simply shows that we can manipulate the component on the fly even after it gets created. The ID configuration It's a good idea to include an id configuration in all of your components. This makes it possible to use Ext.getCmp() to get to those components, later on, when we need them. Remember to keep the ID of every component unique. If you plan on creating multiple copies of a component, you will need to make sure that a unique ID is generated for each copy. The Ext.getCmp() method is great for grabbing Sencha Touch components and manipulating them.   Layouts revisited Layouts are another area we need to expand upon. When you start creating your own applications, you will need a firm understanding of how the different layouts affect what you see on the screen. To this end, we are going to start out with a demonstration application that shows how the different layouts work. For the purposes of this demo application, we will create the different components, one at a time, as individual variables. This is done for the sake of readability and should not be considered the best programming style. Remember that any items created this way will take up memory, even if the user never views the component. var myPanel = new Ext.Panel({ ... It is always a much better practice to create your components, using xtype attibutes, within your main container: items: [{ xtype: 'panel', ... This allows Sencha Touch to render the components as they are needed, instead of all at once when the page loads. The card layout To begin with, we will create a simple card layout: new Ext.Application({ name: 'TouchStart', launch: function() { var layoutPanel = new Ext.Panel({ fullscreen: true, layout: 'card', id: 'layoutPanel', cardSwitchAnimation: 'slide', items: [hboxTest] }); this.viewport = layoutPanel; }}); This sets up a single panel with a card layout. The card layout arranges its items similar to a stack of cards. Only one of these cards is active and displayed at a time. The card layout keeps any additional cards in the background and only creates them when the panel receives the setActiveItem() command. Each item in the list can be activated by using setActiveItem() and the item number. This can be a bit confusing, as the numbering of the items is zero-indexed, meaning that you start counting at zero and not one. For example, if you want to activate the fourth item in the list, you would use: layoutPanel.setActiveItem(3); In this case, we are starting out with only a single card/item called hboxTest. We need to add this container to make our program run. The hbox layout Above the line that says var layoutPanel = new Ext.Panel({, in the preceding code, add the following code: var hboxTest = new Ext.Container({ layout: { type: 'hbox', align: 'stretch' }, items: [{ xtype: 'container', flex: 1, html: 'My flex is 1', margin: 5, style: 'background-color: #7FADCF' }, { xtype: 'container', flex: 2, html: 'My flex is 2', margin: 5, style: 'background-color: #7FADCF' }, { xtype: 'container', width: 80, html: 'My width is 80', margin: 5, style: 'background-color: #7FADCF' }]}); This gives us a container with an hbox layout and three child items. Child and parent In Sencha Touch, we often find ourselves dealing with very large arrays of items, nested in containers that are in turn nested in other containers. It is often helpful to refer to a container as a parent to any items it contains. These items are then referred to as the children of the container. The hbox layout stacks its items horizontally and uses the width and flex values to determine how much horizontal space each of its child items will take up. The align: 'stretch' configuration causes the items to stretch to fill all of the available vertical space. If we run the code now, we should see this: You should try adjusting the flex and width values to see how it affects the size of the child containers. You can also change the available configuration options for align (center, end, start, and stretch), to see the different options available. Once you are finished, let's move on and add some more items to our card layout.  
Read more
  • 0
  • 0
  • 3236

article-image-various-subsystem-configurations
Packt
25 Jun 2014
8 min read
Save for later

Various subsystem configurations

Packt
25 Jun 2014
8 min read
(For more resources related to this topic, see here.) In a high-performance environment, every costly resource instantiation needs to be minimized. This can be done effectively using pools. The different subsystems in WildFly often use various pools of resources to minimize the cost of creating new ones. These resources are often threads or various connection objects. Another benefit is that the pools work as a gatekeeper, hindering the underlying system from being overloaded. This is performed by preventing client calls from reaching their target if a limit has been reached. In the upcoming sections of this article, we will provide an overview of the different subsystems and their pools. The thread pool executor subsystem The thread pool executor subsystem was introduced in JBoss AS 7. Other subsystems can reference thread pools configured in this one. This makes it possible to normalize and manage the thread pools via native WildFly management mechanisms, and it allows you to share thread pools across subsystems. The following code is an example taken from the WildFly Administration Guide (https://docs.jboss.org/author/display/WFLY8/Admin+Guide) that describes how the Infinispan subsystem may use the subsystem, setting up four different pools: <subsystem > <thread-factory name="infinispan-factory" priority="1"/> <bounded-queue-thread-pool name="infinispan-transport"> <core-threads count="1"/> <queue-length count="100000"/> <max-threads count="25"/> <thread-factory name="infinispan-factory"/> </bounded-queue-thread-pool> <bounded-queue-thread-pool name="infinispan-listener"> <core-threads count="1"/> <queue-length count="100000"/> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </bounded-queue-thread-pool> <scheduled-thread-pool name="infinispan-eviction"> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </scheduled-thread-pool> <scheduled-thread-pool name="infinispan-repl-queue"> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </scheduled-thread-pool> </subsystem> ... <cache-container name="web" default-cache="repl"listener-executor= "infinispan-listener" eviction-executor= "infinispan-eviction"replication-queue-executor ="infinispan-repl-queue"> <transport executor="infinispan-transport"/> <replicated-cache name="repl" mode="ASYNC" batching="true"> <locking isolation="REPEATABLE_READ"/> <file-store/> </replicated-cache> </cache-container> The following thread pools are available: unbounded-queue-thread-pool bounded-queue-thread-pool blocking-bounded-queue-thread-pool queueless-thread-pool blocking-queueless-thread-pool scheduled-thread-pool The details of these thread pools are described in the following sections: unbounded-queue-thread-pool The unbounded-queue-thread-pool thread pool executor has the maximum size and an unlimited queue. If the number of running threads is less than the maximum size when a task is submitted, a new thread will be created. Otherwise, the task is placed in a queue. This queue is allowed to grow infinitely. The configuration properties are shown in the following table: max-threads Max allowed threads running simultaneously keepalive-time This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) thread-factory This specifies the thread factory to use to create worker threads. bounded-queue-thread-pool The bounded-queue-thread-pool thread pool executor has a core, maximum size, and a specified queue length. If the number of running threads is less than the core size when a task is submitted, a new thread will be created; otherwise, it will be put in the queue. If the queue's maximum size has been reached and the maximum number of threads hasn't been reached, a new thread is also created. If max-threads is hit, the call will be sent to the handoff-executor. If no handoff-executor is configured, the call will be discarded. The configuration properties are shown in the following table: core-threads Optional and should be less that max-threads queue-length This specifies the maximum size of the queue. max-threads This specifies the maximum number of threads that are allowed to run simultaneously. keepalive-time This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) Handoff-executor This specifies an executor to which tasks will be delegated, in the event that a task cannot be accepted. allow-core-timeout This specifies whether core threads may time-out; if false, only threads above the core size will time-out. thread-factory This specifies the thread factory to use to create worker threads. blocking-bounded-queue-thread-pool The blocking-bounded-queue-thread-pool thread pool executor has a core, a maximum size and a specified queue length. If the number of running threads is less than the core size when a task is submitted, a new thread will be created. Otherwise, it will be put in the queue. If the queue's maximum size has been reached, a new thread is created; if not, max-threads is exceeded. If so, the call is blocked. The configuration properties are shown in the following table: core-threads Optional and should be less that max-threads queue-length This specifies the maximum size of the queue. max-threads This specifies the maximum number of simultaneous threads allowed to run. keepalive-time This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) allow-core-timeout This specifies whether core threads may time-out; if false, only threads above the core size will time-out. thread-factory This specifies the thread factory to use to create worker threads queueless-thread-pool The queueless-thread-pool thread pool is a thread pool executor without any queue. If the number of running threads is less than max-threads when a task is submitted, a new thread will be created; otherwise, the handoff-executor will be called. If no handoff-executor is configured the call will be discarded. The configuration properties are shown in the following table: max-threads Max allowed threads running simultaneously keepalive-time The amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) handoff-executor Specifies an executor to delegate tasks to in the event that a task cannot be accepted thread-factory The thread factory to use to create worker threads blocking-queueless-thread-pool The blocking-queueless-thread-pool thread pool executor has no queue. If the number of running threads is less than max-threads when a task is submitted, a new thread will be created. Otherwise, the caller will be blocked. The configuration properties are shown in the following table: max-threads Max allowed threads running simultaneously keepalive-time This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) thread-factory This specifies the thread factory to use to create worker threads scheduled-thread-pool The scheduled-thread-pool thread pool is used by tasks that are scheduled to trigger at a certain time. The configuration properties are shown in the following table: max-threads Max allowed threads running simultaneously keepalive-time This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) thread-factory This specifies the thread factory to use to create worker threads Monitoring All of the pools just mentioned can be administered and monitored using both CLI and JMX (actually, the Admin Console can be used to administer, but not see, any live data). The following example and screenshots show the access to an unbounded-queue-thread-pool called test. Using CLI, run the following command: /subsystem=threads/unbounded-queue-thread-pool=test:read-resource (include-runtime=true) The response to the preceding command is as follows: { "outcome" => "success", "result" => { "active-count" => 0, "completed-task-count" => 0L, "current-thread-count" => 0, "keepalive-time" => undefined, "largest-thread-count" => 0, "max-threads" => 100, "name" => "test", "queue-size" => 0, "rejected-count" => 0, "task-count" => 0L, "thread-factory" => undefined } } Using JMX (query and result in the JConsole UI), run the following code: jboss.as:subsystem=threads,unbounded-queue-thread-pool=test An example thread pool by JMX is shown in the following screenshot: An example thread pool by JMX The following screenshot shows the corresponding information in the Admin Console Example thread pool—Admin Console The future of the thread subsystem According to the official JIRA case WFLY-462 (https://issues.jboss.org/browse/WFLY-462), the central thread pool configuration has been targeted for removal in future versions of the application server. It is, however, uncertain that all subprojects will adhere to this. The actual configuration will then be moved out to the subsystem itself. This seems to be the way the general architecture of WildFly is moving in terms of pools—moving away from generic ones and making them subsystem-specific. The different types of pools described here are still valid though. Note that, contrary to previous releases, Stateless EJB is no longer pooled by default. More information of this is available in the JIRA case WFLY-1383. It can be found at https://issues.jboss.org/browse/WFLY-1383.
Read more
  • 0
  • 0
  • 3235
article-image-working-nav-and-azure-app-service
Packt
30 Jan 2017
12 min read
Save for later

Working with NAV and Azure App Service

Packt
30 Jan 2017
12 min read
In this article by Stefano Demiliani, the author of the book Building ERP Solutions with Microsoft Dynamics NAV, we will experience the quick solution to solve complex technical architectural scenarios and create external applications within a blink of an eye using Microsoft Dynamics NAV. (For more resources related to this topic, see here.) The business scenario Imagine a requirement where many Microsoft Dynamics NAV instances (physically located at different places around the world) have to interact with an external application. A typical scenario could be a headquarter of a big enterprise company that has a business application (called HQAPP) that must collect data about item shipments from the ERP of the subsidiary companies around the world (Microsoft Dynamics NAV): The cloud could help us to efficiently handle this scenario. Why not place the interface layer in the Azure Cloud and use the scalability features that Azure could offer? Azure App Service could be the solution to this. We can implement an architecture like the following schema: Here, the interface layer is placed on Azure App Service. Every NAV instance has the business logic (in our scenario, a query to retrieve the desired data) exposed as an NAV Web Service. The NAV instance can have an Azure VPN in place for security. HQAPP performs a request to the interface layer in Azure App Service with the correct parameters. The cloud service then redirects the request to the correct NAV instance and retrieves the data, which in turn is forwarded to HQAPP. Azure App Service can be scaled (manually or automatically) based on the resources requested to perform the data retrieval process. Azure App Service overview Azure App Service is a PaaS service for building scalable web and mobile apps and enabling interaction with on-premises or on-cloud data. With Azure App Service, you can deploy your application to the cloud and you can quickly scale your application to handle high traffic loads and manage traffic and application availability without interacting with the underlying infrastructure. This is the main difference with Azure VM, where you can run a web application on the cloud but in a IaaS environment (you control the infrastructure like OS, configuration, installed services, and so on). Some key features of Azure App Service are as follows: Support for many languages and frameworks Global scale with high availability (scaling up and out manually or automatically) Security Visual Studio integration for creating, deploying and debugging applications Application templates and connectors available Azure App Service offers different types of resources for running a workload, which are as follows: Web Apps: This hosts websites and web applications Mobile Apps: This hosts mobile app backends API Apps: This hosts RESTful APIs Logic Apps: This automates business processes across the cloud Azure App Service has the following different service plans where you can scale from depending on your requirements in terms of resources: Free: This is ideal for testing and development, no custom domains or SSL are required, you can deploy up to 10 applications. Shared: This has a fixed per-hour charge. This is ideal for testing and development, supports for custom domains and SSL, you can deploy up to 100 applications. Basic: This has a per-hour charge based on the number of instances. It runs on a dedicated instance. This is ideal for low traffic requirements, you can deploy an unlimited number of apps. It supports only a single SSL certificate per plan (not ideal if you need to connect to an Azure VPN or use deployment slots). Standard: This has a per-hour charge based on the number of instances. This provides full SSL support. This provides up to 10 instances with auto-scaling, automated backups, up to five deployment slots, ideal for production environments. Premium: This has per-hour charge based on the number of instances. This provides up to 50 instances with auto-scaling, up to 20 deployment slots, different daily backups, dedicated App Service Environment. Ideal for enterprise scale and integration. Regarding the application deployment, Azure App Service supports the concept of Deployment Slot (only on the Standard and Premium tiers). Deployment Slot is a feature that permits you to have a separate instance of an application that runs on the same VM but is isolated from the other deployment slots and production slots active in the App Service. Always remember that all Deployment Slots share the same VM instance and the same server resources. Developing the solution Our solution is essentially composed of two parts: The NAV business logic The interface layer (cloud service) The following steps will help you retrieve the required data from an external application: In the NAV instances of the subsidiary companies, we need to retrieve the sales shipment's data for every item. To do so, we need to create a Query object that reads Sales Shipment Header and Sales Shipment Line and exposes them as web services (OData).The Query object will be designed as follows: For every Sales Shipment Header web service, we retrieve the corresponding Sales Shipment Lines web service that have Type as DataItem: I've changed the name of the field No. in Sales Shipment Line in DataItem as ItemNo because the default name was in used in Sales Shipment Header in DataItem. Compile and save the Query object (here, I've used Object ID as 50009 and Service Name as Item Shipments). Now, we will publish the Query object as web service in NAV, so open the Web Services page and create the following entries:    Object Type: Query    Object ID: 50009    Service Name: Item Shipments    Published: TRUE When published, NAV returns the OData service URL. This Query object must be published as web service on every NAV instances in the subsidiary companies. To develop our interface layer, we need first to download and install (if not present) the Azure SDK for Visual Studio from https://azure.microsoft.com/en-us/downloads/. After that, we can create a new Azure Cloud Service project by opening Visual Studio and navigate to File | New | Project, select the Cloud templates, and choose Azure Cloud Service. Select the project's name (here, it is NAVAzureCloudService) and click on OK. After clicking on OK, Visual Studio asks you to select a service type. Select WCF Service Web Role, as shown in the following screenshot: Visual Studio now creates a template for our solution. Now right-click on the NAVAzureCloudService project and select New Web Role Project, and in the Add New .NET Framework Role Project window, select WCF Service Web Role and give it a proper name (here, we have named it WCFServiceWebRoleNAV): Then, rename Service1.svc with a better name (here, it is NAVService.svc). Our WCF Service Web Role must have the reference to all the NAV web service URLs for the various NAV instances in our scenario and (if we want to use impersonation) the credentials to access the relative NAV instance. You can right-click the WCFServiceWebRoleNAV project, select Properties and then the Settings tab. Here you can add the URL for the various NAV instances and the relative web service credentials. Let's start writing our service code. We create a class called SalesShipment that defines our data model as follows: public class SalesShipment { public string No { get; set; } public string CustomerNo { get; set; } public string ItemNo { get; set; } public string Description { get; set; } public string Description2 { get; set; } public string UoM { get; set; } public decimal? Quantity { get; set; } public DateTime? ShipmentDate { get; set; } } In next step, we have to define our service contract (interface). Our service will have a single method to retrieve shipments for a NAV instance and with a shipment date filter. The service contract will be defined as follows: public interface INAVService { [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "getShipments?instance={NAVInstanceName}&date={shipmentDateFilter}"] List<SalesShipment> GetShipments(string NAVInstanceName, string shipmentDateFilter); //Date format parameter: YYYY-MM-DD } The WCF service definition will implement the previously defined interface as follows: public class NAVService : INAVService { } The GetShipments method is implemented as follows: public List<SalesShipment> GetShipments(string NAVInstanceName, string shipmentDateFilter) { try { DataAccessLayer.DataAccessLayer DAL = new DataAccessLayer.DataAccessLayer(); List<SalesShipment> list = DAL.GetNAVShipments(NAVInstanceName, shipmentDateFilter); return list; } catch(Exception ex) { // You can handle exceptions here… throw ex; } } This method creates an instance of a DataAccessLayer class (which we will discuss in detail later) and calls a method called GetNAVShipments by passing the NAV instance name and ShipmentDateFilter. To call the NAV business logic, we need to have a reference to the NAV OData web service (only to generate a proxy class, the real service URL will be dynamically called by code) so right-click on your project (WCFServiceWebRoleNAV) and navigate to Add | Service Reference. In the Add Service Reference window, paste the OData URL that comes from NAV and when the service is discovered, give it a reference name (here, it is NAVODATAWS). Visual Studio automatically adds a service reference to your project. The DataAccessLayer class will be responsible for handling calls to the NAV OData web service. This class defines a method called GetNAVShipments with the following two parameters: NAVInstanceName: This is the name of the NAV instance to call shipmentDateFilter: This filters date for the NAV shipment lines (greater than or equal to) According to NAVInstanceName, the method retrieves from the web.config file (appSettings) the correct NAV OData URL and credentials, calls the NAV query (by passing filters), and retrieves the data as a list of SalesShipment records (our data model). The DataAccessLayer class is defined as follows: public List<SalesShipment> GetNAVShipments(string NAVInstanceName, string shipmentDateFilter) { try { string URL = Properties.Settings.Default[NAVInstanceName].ToString(); string WS_User = Properties.Settings.Default[NAVInstanceName + "_User"].ToString(); string WS_Pwd = Properties.Settings.Default[NAVInstanceName + "_Pwd"].ToString(); string WS_Domain = Properties.Settings.Default[NAVInstanceName + "_Domain"].ToString(); DataServiceContext context = new DataServiceContext(new Uri(URL)); NAVODATAWS.NAV NAV = new NAVODATAWS.NAV(new Uri(URL)); NAV.Credentials = new System.Net.NetworkCredential(WS_User, WS_Pwd, WS_Domain); DataServiceQuery<NAVODATAWS.ItemShipments> q = NAV.CreateQuery<NAVODATAWS.ItemShipments>("ItemShipments"); if (shipmentDateFilter != null) { string FilterValue = string.Format("Shipment_Date ge datetime'{0}'", shipmentDateFilter); q = q.AddQueryOption("$filter", FilterValue); } List<NAVODATAWS.ItemShipments> list = q.Execute().ToList(); List<SalesShipment> sslist = new List<SalesShipment>(); foreach (NAVODATAWS.ItemShipments shpt in list) { SalesShipment ss = new SalesShipment(); ss.No = shpt.No; ss.CustomerNo = shpt.Sell_to_Customer_No; ss.ItemNo = shpt.ItemNo; ss.Description = shpt.Description; ss.Description2 = shpt.Description_2; ss.UoM = shpt.Unit_of_Measure; ss.Quantity = shpt.Quantity; ss.ShipmentDate = shpt.Shipment_Date; sslist.Add(ss); } return sslist; } catch (Exception ex) { throw ex; } } The method returns a list of the SalesShipment objects. It creates an instance of the NAV OData web service, applies the OData filter to the NAV query, reads the results, and loads the list of the SalesShipment objects. Deployment to Azure App Service Now that your service is ready, you have to deploy it to the Azure App Service by performing the following steps: Right-click on the NAVAzureCloudService project and select Package… as shown in the following screenshot: In the Package Azure Application window, select Service configuration as Cloud and Build configuration as Release, and then click on Package as shown in the following screenshot: This operation creates two files in the <YourProjectName>binReleaseapp.publish folder as shown in the following screenshot: These are the packages that must be deployed to Azure. To do so, you have to log in to the Azure Portal and navigate to Cloud Services | Add from the hub menu at the left. In the next window, set the following cloud service parameters: DNS name: This depicts name of your cloud service (yourname.cloudapp.net) Subscription: This is the Azure Subscription where the cloud service will be added Resource group: This creates a new resource group for your cloud service or use existing one Location: This is the Azure location where the cloud service is to be added Finally, you can click on the Create button to create your cloud service. Now, deploy the previously created cloud packages to your cloud service that was just created. In the cloud services list, click on NAVAZureCloudService, and in the next window, select the desired slot (for example, Production slot) and click on Upload as shown in the following screenshot: In the Upload a package window, provide the following parameters: Storage account: This is a previously created storage account for your subscription Deployment label: This is the name of your deployment Package: Select the .cspkg file previously created for your cloud service Configuration: Select the .cspkg file previously created for your cloud service configuration You can take a look at the preceding parameters in the following screenshot: Select the Start deployment checkbox and click on the OK button at the bottom to start the deployment process to Azure. Now you can start your cloud service and manage it (swap, scaling, and so on) directly from the Azure Portal: When running, you can use your deployed service by reaching this URL: http://navazurecloudservice.cloudapp.net/NAVService.svc This is the URL that the HQAPP in our business scenario has to call for retrieving data from the various NAV instances of the subsidiary companies around the world. In this way, you have deployed a service to the cloud, you can manage the resources in a central way (via the Azure Portal), and you can easily have different environments by using slots. Summary In this article, you learned to enable NAV instances placed at different locations to interact with an external application through Azure App Service and also the features that it provides. Resources for Article: Further resources on this subject: Introduction to NAV 2017 [article] Code Analysis and Debugging Tools in Microsoft Dynamics NAV 2009 [article] Exploring Microsoft Dynamics NAV – An Introduction [article]
Read more
  • 0
  • 0
  • 3234

article-image-using-spring-faces
Packt
28 Oct 2009
13 min read
Save for later

Using Spring Faces

Packt
28 Oct 2009
13 min read
Using Spring Faces Module The following section shows you how to use the Spring Faces module. Overview of all tags of the Spring Faces tag library The Spring Faces module comes with a set of components, which are provided through a tag library. If you want more detailed information about the tag library, look at the following files inside the Spring Faces source distribution: spring-faces/src/main/resources/META-INF/spring-faces.tld spring-faces/src/main/resources/META-INF/springfaces.taglib.xml spring-faces/src/main/resources/META-INF/faces-config.xml If you want to see the source code of a specific tag, refer to faces-config.xml and springfaces.taglib.xml to get the name of the class of the component. The spring-faces.tld file can be used for documentation issues. The following table should give you a short description about the available tags from the Spring Faces component library: Name of the tag Description includeStyles The includeStyles tag renders the necessary CSS stylesheets which are essential for the components from Spring Faces. The usage of this tag in the head section is recommended for performance optimization. If the tag isn't included, the necessary stylesheets are rendered on the first usage of the tag. If you are using a template for your pages, it's a good pattern to include the tag in the header of that template. For more information about performance optimization, refer to the Yahoo performance guidelines, which are available at the following URL: http://developer.yahoo.com/performance. Some tags (includeStyles, resource, and resourceGroup) of the Spring Faces tag library are implementing patterns to optimize the performance on client side. resource The resource tag loads and renders a resource with ResourceServlet. You should prefer this tag instead of directly including a CSS stylesheet or a JavaScript file because ResourceServlet sets the proper response headers for caching the resource file. resourceGroup With the resourceGroup tag, it is possible to combine all resources which are inside the tag. It is important that all resources are the same type. The tag uses ResourceServlet with the appended parameter to create one resource file which is sent to the client. clientTextValidator With the clientTextValidator tag, you can validate a child inputText element. For the validation, you have an attribute called regExp where you can provide a regular expression. The validation is done on client side. clientNumberValidator With the clientNumberValidator tag, you can validate a child inputText element. With the provided validation methods, you can check whether the text is a number and check some properties for the number, e.g. range. The validation is done on client side. clientCurrencyValidator With the clientCurrencyValidator tag, you can validate a child inputText element. This tag should be used if you want to validate a currency. The validation is done on client side. clientDateValidator With the clientDateValidator tag, you can validate a child inputText element. The tag should be used to validate a date. The field displays a pop-up calendar. The validation is done on client side. validateAllOnClick With the validateAllOnClick tag, you can execute all client-side validation on the click of a specific element. That can be useful for a submit button. commandButton With the commandButton tag, it is possible to execute an arbitrary method on an instance. The method itself has to be a public method with no parameters and a java.lang.Object instance as the return value. commandLink The commandLink tag renders an AJAX link. With the processIds attribute, you can provide the ids of components which should be processed through the process. ajaxEvent The ajaxEvent tag creates a JavaScript event listener. This tag should only be used if you can ensure that the client has JavaScript enabled. A complete example After we have shown the main configuration elements and described the Spring Faces components, the following section shows a complete example in order to get a good understanding about how to work with the Spring Faces module in your own web application. The following diagram shows the screen of the sample application. With the shown screen, it is possible to create a new issue and save it to the bug database. It is not part of this example to describe the bug database or to describe how to work with databases in general. The sample uses the model classes. The diagram has three required fields. These fields are: Name: The name of the issue Description: A short description for the issue Fix until: The fixing date for the issue Additionally, there are the following two buttons: store: With a click on the store button, the system tries to create a new issue that includes the provided information cancel: With a click on the cancel button, the system ignores the data which is entered and navigates to the overview page. Now, the first step is to create the implementation of that input page. That implementation and its description are shown in the section below. Creating the input page As we described above, we use Facelets as a view handler technology. Therefore, the pages have to be defined with XHTML, with .xhtml as the file extension. The name for the input page will be add.xhtml. For the description, we separate the page into the following five parts: Header Name Description Fix until The Buttons This separation is shown in the diagram below: The Header part The first step in the header is to define that we have an XHTML page. This is done through the definition of the correct doctype. <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> An XHTML page is described as an XML page. If you want to use special tags inside the XML page, you have to define a namespace for that. For a page with Facelets and Spring Faces, we have to define more than one namespace. The following table describes those namespaces: Namespace Description http://www.w3.org/1999/xhtml The namespace for XHTML itself. http://java.sun.com/jsf/facelets The Facelet defines some components (tags). These components are available under this namespace. http://java.sun.com/jsf/html The user interface components of JSF are available under this namespace. http://java.sun.com/jsf/core The core tags of JSF, for example converter, can be accessed under this namespace. http://www.springframework.org/tags/faces The namespace for the Spring Faces component library. For the header definition, we use the composition component of the Facelets components. With that component, it is possible to define a template for the layout. This is very similar to the previously mentioned Tiles framework. The following code snippet shows you the second part (after the doctype) of the header definition: A description and overview of the JSF tags is available at: http://developers.sun.com/jscreator/archive/learning/bookshelf/pearson/corejsf/standard_jsf_tags.pdf. <ui:composition template="/WEB-INF/layouts/standard.xhtml"> With the help of the template attribute, we refer to the used layout template. In our example, we refer to /WEB-INF/layouts/standard.xhtml. The following code shows the complete layout file standard.xhtml. This layout file is also described with the Facelets technology. Therefore, it is possible to use Facelets components inside that page, too. Additionally, we use Spring Faces components inside that layout page. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <f:view contentType="text/html"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>flow.tracR</title> <sf:includeStyles/> <sf:resourceGroup> <sf:resource path="/css-framework/css/tools.css"/> <sf:resource path="/css-framework/css/typo.css"/> <sf:resource path="/css-framework/css/forms.css"/> <sf:resource path="/css-framework/css/layout-navtop-localleft. css"/> <sf:resource path="/css-framework/css/layout.css"/> </sf:resourceGroup> <sf:resource path="/css/issue.css"/> <ui:insert name="headIncludes"/> </head> <body class="tundra spring"> <div id="page"> <div id="content"> <div id="main"> <ui:insert name="content"/> </div> </div> </div> </body> </f:view> </html> The Name part The first element in the input page is the section for the input of the name. For the description of that section, we use elements from the JSF component library. We access this library with h as the prefix, which we have defined in the header section. For the general layout, we use standard HTML elements, such as the div element. The definition is shown below. <div class="field"> <div class="label"> <h:outputLabel for="name">Name:</h:outputLabel> </div> <div class="input"> <h:inputText id="name" value="#{issue.name}" /> </div> </div> The Description part The next element in the page is the Description element. The definition is very similar to the Name part. Instead of the definition of the Name part, we use the element description inside the h:inputText element—the required attribute with true as its value. This attribute tells the JSF system that the issue.description value is mandatory. If the user does not enter a value, the validation fails. <div class="field"> <div class="label"> <h:outputLabel for="description">Description:</h:outputLabel> </div> <div class="input"> <h:inputText id="description" value="#{issue.description}" required="true"/> </div> </div> The Fix until part The last input section is the Fix until part. This field is a very common field in web applications, because there is often the need to input a date. Internally, a date is often represented through an instance of the java.util.Date class. The text which is entered by the user has to be validated and converted in order to get a valid instance. To help the user with the input, a calendar for the input is often used. The Spring Faces library offers a component which shows a calendar and adds client-side validation. The complete definition of the Fix until part is shown below. The name of the component is clientDateValidator. The clientDateValidator component is used with sf as the prefix. This prefix is defined in the namespace definition in the shown header of the add.xhtml page. <div class="field"> <div class="label"> <h:outputLabel for="checkinDate">Fix until:</h:outputLabel> </div> <div class="input"> <sf:clientDateValidator required="true" invalidMessage="pleaseinsert a correct fixing date. format: dd.MM.yyyy"promptMessage="Format: dd.MM.yyyy, example: 01.01.2020"> <h:inputText id="checkinDate" value="#{issue.fixingDate}" required="true"> <f:convertDateTime pattern="dd.MM.yyyy" timeZone="GMT"/> </h:inputText> </sf:clientDateValidator> </div> </div> In the example above, we use the promptMessage attribute to help the user with the format. The message is shown when the user sets the cursor on the input element. If the validation fails, the message of the invalidMessage attribute is used to show the user that a wrong formatted input has been entered. The Buttons part The last element in the page are the buttons. For these buttons, the commandButton component from Spring Faces is used. The definition is shown below: <div class="buttonGroup"> <sf:commandButton id="store" action="store" processIds="*" value="store"/> <sf:commandButton id="cancel" action="cancel" processIds="*" value="cancel"/> </div> It is worth mentioning that JavaServer Faces binds an action to the action method of a backing bean. Spring Web Flow binds the action to events. Handling of errors It's possible to have validation on the client side or on the server side. For the Fix until element, we use the previously mentioned clientDateValidator component of the Spring Faces library. The following figure shows how this component shows the error message to the user: Reflecting the actions of the buttons into the flow definition file Clicking the buttons executes an action that has a transition as the result. The name of the action is expressed in the action attribute of the button component which is implemented as commandButton from the Spring Faces component library. If you click on the store button, the validation is executed first. If you want to prevent that validation, you have to use the bind attribute and set it to false. This feature is used for the cancel button, because in this state it is necessary to ignore the inputs. <view-state id="add" model="issue"> <transition on="store" to="issueStore" > <evaluate expression="persistenceContext.persist(issue)"/> </transition> <transition on="cancel" to="cancelInput" bind="false"> </transition> </view-state> Showing the results To test the implemented feature, we implement an overview page. We have the choice to implement the page as a flow with one view state or implement it as a simple JSF view. Independent from that choice, we will use Facelets to implement that overview page, because Facelets does not depend on the Spring Web Flow Framework as it is a feature of JSF. The example uses a table to show the entered issues. If no issue is entered, a message is shown to the user. The figure below shows this table with one row of data. The Id is a URL. If you click on this link, the input page is shown with the data of that issue. With data, we execute an update. The indicator for that is the valid ID of the issue. If your data is available, the No issues in database message is shown to the user. This is done with a condition on the outputText component. See the code snippet below: <h:outputText id="noIssuesText" value="No Issues in the database" rendered="#{empty issueList}"/> For the table, we use the dataTable component. <h:dataTable id="issues" value="#{issueList}" var="issue"rendered="#{not empty issueList}" border="1"> <h:column> <f:facet name="header">Id</f:facet> <a href="add?id=#{issue.id}">#{issue.id}</a> </h:column> <h:column> <f:facet name="header">Name</f:facet> #{issue.name} </h:column> <h:column> <f:facet name="header">fix until</f:facet> #{issue.fixingDate} </h:column> <h:column> <f:facet name="header">creation date</f:facet> #{issue.creationDate} </h:column> <h:column> <f:facet name="header">last modified</f:facet> #{issue.lastModified} </h:column> </h:dataTable>
Read more
  • 0
  • 0
  • 3234

article-image-using-webrtc-data-api
Packt
09 May 2014
10 min read
Save for later

Using the WebRTC Data API

Packt
09 May 2014
10 min read
(For more resources related to this topic, see here.) What is WebRTC? Web Real-Time Communication is a new (still under an active development) open framework for the Web to enable browser-to-browser applications for audio/video calling, video chat, peer-to-peer file sharing without any third-party additional software/plugins. It was open sourced by Google in 2011 and includes the fundamental building components for high-quality communications on the Web. These components, when implemented in a browser, can be accessed through a JavaScript API, enabling developers to build their own rich, media web applications. Google, Mozilla, and Opera support WebRTC and are involved in the development process. Major components of WebRTC API are as follows: getUserMedia: This allows a web browser to access the camera and microphone PeerConnection: This sets up audio/video calls DataChannels: This allow browsers to share data via peer-to-peer connection Benefits of using WebRTC in your business Reducing costs: It is a free and open source technology. You don't need to pay for complex proprietary solutions ever. IT deployment and support costs can be lowered because now you don't need to deploy special client software for your customers. Plugins?: You don't need it ever. Before now you had to use Flash, Java applets, or other tricky solutions to build interactive rich media web applications. Customers had to download and install third-party plugins to be able using your media content. You also had to keep in mind different solutions/plugins for variety of operating systems and platforms. Now you don't need to care about it. Peer-to-peer communication: In most cases communication will be established directly between your customers and you don't need to have a middle point. Easy to use: You don't need to be a professional programmer or to have a team of certified developers with some kind of specific knowledge. In a basic case, you can easily integrate WebRTC functionality into your web services/sites by using open JavaScript API or even using a ready-to-go framework. Single solution for all platforms: You don't need to develop special native version of your web service for different platforms (iOS, Android, Windows, or any other). WebRTC is developed to be a cross-platform and universal tool. WebRTC is open source and free: Community can discover new bugs and solve them effectively and quick. Moreover, it is developed and standardized by Mozilla, Google, and Opera—world software companies. Topics The article covers the following topics: Developing a WebRTC application: You will learn the basics of the technology and build a complete audio/video conference real-life web application. We will also talk on SDP (Session Description Protocol), signaling, client-server sides' interoperation, and configuring STUN and TURN servers. In Data API, you will learn how to build a peer-to-peer, cross-platform file sharing web service using the WebRTC Data API. Media streaming and screen casting introduces you into streaming prerecorded media content peer-to-peer and desktop sharing. In this article, you will build a simple application that provides such kind of functionality. Nowadays, security and authentication is very important topic and you definitely don't want to forget on it while developing your applications. So, in this article, you will learn how to make your WebRTC solutions to be secure, why authentication might be very important, and how you can implement this functionality in your products. Nowadays, mobile platforms are literally part of our life, so it's important to make your interactive application to be working great on mobile devices also. This article will introduce you into aspects that will help you in developing great WebRTC products keeping mobile devices in mind. Session Description Protocol SDP is an important part of WebRTC stack. It used to negotiate on session/media options during establishing peer connection. It is a protocol intended for describing multimedia communication sessions for the purposes of session announcement, session invitation, and parameter negotiation. It does not deliver media data itself, but is used for negotiation between peers of media type, format, and all associated properties/options (resolution, encryption, codecs, and so on). The set of properties and parameters are usually called a session profile. Peers have to exchange SDP data using signaling channel before they can establish a direct connection. The following is example of an SDP offer: v=0 o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com s= c=IN IP4 host.atlanta.example.com t=0 0 m=audio 49170 RTP/AVP 0 8 97 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:97 iLBC/8000 m=video 51372 RTP/AVP 31 32 a=rtpmap:31 H261/90000 a=rtpmap:32 MPV/90000 Here we can see that this is a video and audio session, and multiple codecs are offered. The following is example of an SDP answer: v=0 o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com s= c=IN IP4 host.biloxi.example.com t=0 0 m=audio 49174 RTP/AVP 0 a=rtpmap:0 PCMU/8000 m=video 49170 RTP/AVP 32 a=rtpmap:32 MPV/90000 Here we can see that only one codec is accepted in reply to the offer above. You can find more SDP sessions examples at https://www.rfc-editor.org/rfc/rfc4317.txt. You can also find in-dept details on SDP in the appropriate RFC at http://tools.ietf.org/html/rfc4566. Configuring and installing your own STUN server As you already know, it is important to have an access to STUN/TURN server to work with peers located behind NAT or firewall. In this article, developing our application, we used pubic STUN servers (actually, they are public Google servers accessible from other networks). Nevertheless, if you plan to build your own service, you should install your own STUN/TURN server. This way your application will not be depended on a server you even can't control. Today we have public STUN servers from Google, tomorrow they can be switched off. So, the right way is to have your own STUN/TURN server. In this section, you will be introduced to installing STUN server as the simpler case. There are several implementations of STUN servers that can be found on the Internet. You can take one from http://www.stunprotocol.org. It is cross-platform and can be used under Windows, Mac OS X, or Linux. To start STUN server, you should use the following command line: stunserver --mode full --primaryinterface x1.x1.x1.x1 --altinterface x2.x2.x2.x2 Please, pay attention that you need two IP addresses on your machine to run STUN server. It is mandatory to make STUN protocol work correct. The machine can have only one physical network interface, but it should have then a network alias with IP address different of that used on the main network interface. WebSocket WebSocket is a protocol that provides full-duplex communication channels over a single TCP connection. This is a relatively young protocol but today all major web browsers including Chrome, Internet Explorer, Opera, Firefox, and Safari support it. WebSocket is a replacement for long-polling to get two-way communications between browser and server. In this article, we will use WebSocket as a transport channel to develop a signaling server for our videoconference service. Using it, our peers will communicate with the signaling server. The two important benefits of WebSocket is that it does support HTTPS (secure channel) and can be used via web proxy (nevertheless, some proxies can block WebSocket protocol). NAT traversal WebRTC has in-built mechanism to use such NAT traversal options like STUN and TURN servers. In this article, we used public STUN (Session Traversal Utilities for NAT) servers, but in real life you should install and configure your own STUN or TURN (Traversal Using Relay NAT) server. In most cases, you will use a STUN server. It helps to do NAT/firewall traversal and establish direct connection between peers. In other words, STUN server is utilized during connection establishing stage only. After the connection has been established, peers will transfer media data directly between them. In some cases (unfortunately, they are not so rare), STUN server won't help you to get through a firewall or NAT and establishing direct connection between peers will be impossible. For example, if both peers are behind symmetric NAT. In this case TURN server can help you. TURN server works as a retransmitter between peers. Using TURN server, all media data between peers will be transmitted through the TURN server. If your application gives a list of several STUN/TURN servers to the WebRTC API, the web browser will try to use STUN servers first and in case if connection failed it will try to use TURN servers automatically. Preparing environment We can prepare the environment by performing the following steps: Create a folder for the whole application somewhere on your disk. Let's call it my_rtc_project. Make a directory named my_rtc_project/www here, we will put all the client-side code (JavaScript files or HTML pages). Signaling server's code will be placed under its separate folder, so create directory for it my_rtc_project/apps/rtcserver/src. Kindly note that we will use Git, which is free and open source distributed version control system. For Linux boxes it can be installed using default package manager. For Windows system, I recommend to install and use this implementation: https://github.com/msysgit/msysgit. If you're using Windows box, install msysgit and add path to its bin folder to your PATH environment variable. Installing Erlang The signaling server is developed in Erlang language. Erlang is a great choice to develop server-side applications due to the following reasons: It is very comfortable and easy for prototyping Its processes (aktors) are very lightweight and cheap It does support network operations with no need of any external libraries The code been compiled to a byte code running by a very powerful Erlang Virtual Machine Some great projects The following projects are developed using Erlang: Yaws and Cowboy: These are web servers Riak and CouchDB: These are distributed databases Cloudant: This is a database service based on fork of CouchDB Ejabberd: This is a XMPP instant messaging service Zotonic: This is a Content Management System RabbitMQ: This is a message bus Wings 3D: This is a 3D modeler GitHub: This a web-based hosting service for software development projects that use Git. GitHub uses Erlang for RPC proxies to Ruby processes WhatsApp: This is a famous mobile messenger, sold to Facebook Call of Duty: This computer game uses Erlang on server side Goldman Sachs: This is high-frequency trading computer programs A very brief history of Erlang 1982 to 1985: During this period, Ericsson starts experimenting with programming of telecom. Existing languages do not suit for the task. 1985 to 1986: During this period, Ericsson decides they must develop their own language with desirable features from Lisp, Prolog, and Parlog. The language should have built-in concurrency and error recovery. 1987: In this year, first experiments with the new language Erlang were conducted. 1988: In this year, Erlang firstly used by external users out of the lab. 1989: In this year, Ericsson works on fast implementation of Erlang. 1990: In this year, Erlang is presented on ISS'90 and gets new users. 1991: In this year, Fast implementation of Erlang is released to users. Erlang is presented on Telecom'91, and has compiler and graphic interface. 1992: In this year, Erlang gets a lot of new users. Ericsson ported Erlang to new platforms including VxWorks and Macintosh. 1993: In this year, Erlang gets distribution. It makes it possible to run homogeneous Erlang system on a heterogeneous hardware. Ericsson starts selling Erlang implementations and Erlang Tools. Separate organization in Ericsson provides support. Erlang is supported by many platforms. You can download and install it using the main website: http://www.erlang.org. Summary In this article, we have discussed in detail about the WebRTC technology, and also about the WebRTC API. Resources for Article: Further resources on this subject: Applying WebRTC for Education and E-learning [Article] Spring Roo 1.1: Working with Roo-generated Web Applications [Article] WebSphere MQ Sample Programs [Article]
Read more
  • 0
  • 0
  • 3231
article-image-everything-package-concrete5
Packt
28 Mar 2011
10 min read
Save for later

Everything in a Package with concrete5

Packt
28 Mar 2011
10 min read
  concrete5 Beginner's Guide Create and customize your own website with the Concrete5 Beginner's Guide What's a package? Before we start creating our package, here are a few words about the functionality and purpose of packages: They can hold a single or several themes together You can include blocks which your theme needs You can check the requirements during the installation process in case your package depends on other blocks, configurations, and so on A package can be used to hook into events raised by concrete5 to execute custom code during different kind of actions You can create jobs, which run periodically to improve or check things in your website These are the most important things you can do with a package; some of it doesn't depend on packages, but is easier to handle if you use packages. It's up to you, but putting every extension in a package might even be useful if there's just a single element in it—why? You never have to worry where to extract the add-on. It always belongs in the packages directory An add-on wrapped in a package can be submitted to the concrete5 marketplace allowing you to earn money or make some people in the community happy by releasing your add-on for free Package structure We've already looked at different structures and you are probably already familiar with most of the directories in concrete5. Before we continue, here are a few words about the package structure, as it's essential that you understand its concept before we continue. A package is basically a complete concrete5 structure within one directory. All the directories are optional though. No need to create all of them, but you can create and use all of them within a single package. The directory concrete is a lot like a package as well; it's just located in its own directory and not within packages. Package controller Like the blocks we've created, the package has a controller as well. First of all, it is used to handle the installation process, but it's not limited to that. We can handle events and a few more things in the package controller; there's more about that later in this article. For now, we only need the controller to make sure the dashboard knows the package name and description. Time for action - creating the package controller Carry out the following steps: First, create a new directory named c5book in packages. Within that directory, create a file named controller.php and put the following content in it: <?php defined('C5_EXECUTE') or die(_("Access Denied.")); class c5bookPackage extends Package { protected $pkgHandle = 'c5book'; protected $appVersionRequired = '5.4.0'; protected $pkgVersion = '1.0'; public function getPackageDescription() { return t("Theme, Templates and Blocks from concrete5 for Beginner's"); } public function getPackageName() { return t("c5book"); } public function install() { $pkg = parent::install(); } } ?> You can create a file named icon.png 97 x 97 pixels with 4px rounded transparent corners. This is the official specification that you have to follow if you want to upload your add-on to the concrete5 marketplace. Once you've created the directory and the mandatory controller, you can go to your dashboard and click on Add Functionality. It looks a lot like a block but when you click on Install, the add-on is going to appear in the packages section. What just happened? The controller we created looks and works a lot like a block controller, which you should have seen and created already. However, let's go through all the elements of the package controller anyway, as it's important that you understand them: pkgHandle: A unique handle for your package. You'll need this when you access your package from code. appVersionRequired: The minimum version required to install the add-on. concrete5 will check that during the installation process. pkgVersion: The current version of the package. Make sure that you change the number when you release an update for a package; concrete5 has to know that it is installing an update and not a new version. getPackageDescription: Returns the description of your package. Use the t-function to keep it translatable. getPackageName: The same as above, just a bit shorter. install: You could remove this method in the controller above, since we're only calling its parent method and don't check anything else. It has no influence, but we'll need this method later when we put blocks in our package. It's just a skeleton for the next steps at the moment. Moving templates into package Remember the templates we've created? We placed them in the top level blocks directory. Worked like a charm but imagine what happens when you create a theme which also needs some block templates in order to make sure the blocks look like the theme? You'd have to copy files into the blocks directory as well as themes. This is exactly what we're trying to avoid with packages. It's rather easy with templates; they work almost anywhere. You just have to copy the folder slideshow from blocks to packages/c5book/blocks, as shown in the following screenshot: This step was even easier than most things we did before. We simply moved our templates into a different directory—nothing else. concrete5 looks for custom templates in different places like: concrete/blocks/<block-name>/templates blocks/<block-name>/templates packages/<package-name>/blocks/<block-name>/templates It doesn't matter where you put your templates, concrete5 will find them. Moving themes and blocks into the package Now that we've got our templates in the package, let's move the new blocks we've created into that package as well. The process is similar, but we have to call a method in the installer which installs our block. concrete5 does not automatically install blocks within packages. This means that we have to extend the empty install method shown earlier. Before we move the blocks into the package you should remove all blocks first. To do this, go to your dashboard, click on Add Functionality, click on the Edit button next to the block you want to move, and click on the Remove button in the next screen. We'll start with the jqzoom block. Please note; removing a block will of course, remove all the blocks you've added to your pages. Content will be lost if you move a block into a package after you've already used it. Time for action – moving jQZoom block into the package Carry out the following steps: As mentioned earlier, remove the jqzoom block from you website by using the Add Functionality section in your dashboard. Move the directory blocks/jqzoom to packages/c5book/blocks. Open the package controller we created a few pages earlier; you can find it at packages/c5book/controller.php. The following snippet shows only a part of the controller, the install method. The only thing you have to do is insert the highlighted line: public function install() { $pkg = parent::install(); // install blocks BlockType::installBlockTypeFromPackage('jqzoom', $pkg); } Save the file and go to your dashboard again. Select Add Functionality and locate the c5book package; click on Edit and then Uninstall Package and confirm the process on the next screen. Back on the Add Functionality screen, reinstall the package again, which will automatically install the block. What just happened? Besides moving files, we only had to add a single line of code to our existing package controller. This is necessary, because blocks within packages aren't automatically installed. When installing a package, only the install method of the controller is called, exactly the place where we hook into and install our block. The installBlockTypeFromPackage method takes two parameters: The block handle and the package object. However, this doesn't mean that packages behave like namespaces. What does this mean? A block is connected to a package. This is necessary in order to be able to uninstall the block when removing the package along with some other reasons. Even though there's a connection between the two objects, a block handle must be unique across all packages. You've seen that we had to remove and reinstall the package several times while we only moved a block. At this point, it probably looks a bit weird to do that, especially as you're going to lose some content on your website. However, when you're more familiar with the concrete5 framework, you'll usually know if you're going to need a package and make that decision before you start creating new blocks. If you're still in doubt, don't worry about it too much and create a package and not just a block. Using a package is usually the safest choice. Don't forget that all instances of a block will be removed from all pages when you uninstall the block from your website. Make sure your package structure doesn't change before you start adding content to your website. Time for action - moving the PDF block into the package Some blocks depend on helpers, files and libraries, which aren't in the block directory. The PDF generator block is such an example. It depends on a file found in the tools directory in the root of your concrete5 website. How do we include such a file in a package? Move the pdf directory from blocks to packages/c5book/blocks since we also want to include the block in the package. Locate the c5book directory within packages and create a new subdirectory named tools. Move generate_pdf.php from tools to packages/c5book/tools. Create another directory named libraries in packages/c5book. Move the mpdf50 from libraries to packages/c5book/libraries. As we've moved two objects, we have to make sure our code looks for them in the right place. Open packages/c5book/tools/generate.php and look for Loader::library at the beginning of the file. We have to add a second parameter to Loader::library, as shown here: <?php defined('C5_EXECUTE') or die(_("Access Denied.")); Loader::library('mpdf50/mpdf', 'c5book'); $fh = Loader::helper('file'); $header = <<<EOT <style type="text/css"> body { font-family: Helvetica, Arial; } h1 { border-bottom: 1px solid black; } </style> EOT; Next, open packages/c5book/blocks/pdf/view.php. We have to add the package handle as the second parameter to make sure the tool file is loaded from the package. <!--hidden_in_pdf_start--> <?php defined('C5_EXECUTE') or die(_('Access Denied.')); $nh = Loader::helper('navigation'); $url = Loader::helper('concrete/urls'); $toolsUrl = $url->getToolsURL('generate_pdf', 'c5book'); $toolsUrl .= '?p=' . rawurlencode($nh->getLinkToCollection($this- >c, true)); echo "<a href="{$toolsUrl}">PDF</a>"; ?> <!--hidden_in_pdf_end--> What just happened? In the preceding example, we put got a file in the tools directory and a PDF generator in the libraries directory, which we had to move as well. Even at the risk of saying the same thing several times: A package can contain any element of concrete5—libraries, tools, controllers, images, and so on. By putting all files in a single package directory, we can make sure that all files are installed at once, thus making sure all dependencies are met. Nothing has changed beside the small changes we've made to the commands, which access or load an element. A helper behaves like a helper, no matter where it's located. Have a go hero – move more add-ons We've moved two different blocks into our new package, along with the slideshow block templates. These aren't all blocks we've created so far. Try to move all add-ons we've created into our new package. If you need more information about that process, have a look at the following page: http://www.concrete5.org/documentation/developers/system/packages/
Read more
  • 0
  • 0
  • 3230

article-image-netbeans-platform-69-working-actions
Packt
10 Aug 2010
4 min read
Save for later

NetBeans Platform 6.9: Working with Actions

Packt
10 Aug 2010
4 min read
(For more resources on NetBeans, see here.) In Swing, an Action object provides an ActionListener for Action event handling, together with additional features, such as tool tips, icons, and the Action's activated state. One aim of Swing Actions is that they should be reusable, that is, can be invoked from a menu item as well as a related toolbar button and keyboard shortcut. The NetBeans Platform provides an Action framework enabling you to organize Actions declaratively. In many cases, you can simply reuse your existing Actions exactly as they were before you used the NetBeans Platform, once you have declared them. For more complex scenarios, you can make use of specific NetBeans Platform Action classes that offer the advantages of additional features, such as more complex displays in toolbars and support for context-sensitive help. Preparing to work with global actions Before you begin working with global Actions, let's make some changes to our application. It should be possible for the TaskEditorTopComponent to open for a specific task. You should therefore be able to pass a task into the TaskEditorTopComponent. Rather than the TaskEditorPanel creating a new task in its constructor, the task needs to be passed into it and made available to the TaskEditorTopComponent. On the other hand, it may make sense for a TaskEditorTopComponent to create a new task, rather than providing an existing task, which can then be made available for editing. Therefore, the TaskEditorTopComponent should provide two constructors. If a task is passed into the TaskEditorTopComponent, the TaskEditorTopComponent and the TaskEditorPanel are initialized. If no task is passed in, a new task is created and is made available for editing. Furthermore, it is currently only possible to edit a single task at a time. It would make sense to be able to work on several tasks at the same time in different editors. At the same time, you should make sure that the task is only opened once by the same editor. The TaskEditorTopComponent should therefore provide a method for creating new or finding existing editors. In addition, it would be useful if TaskEditorPanels were automatically closed for deleted tasks. Remove the logic for creating new tasks from the constructor of the TaskEditorPanel, along with the instance variable for storing the TaskManager, which is now redundant: public TaskEditorPanel() { initComponents(); this.pcs = new PropertyChangeSupport(this); } Introduce a new method to update a task: public void updateTask(Task task) { Task oldTask = this.task; this.task = task; this.pcs.firePropertyChange(PROP_TASK, oldTask, this.task); this.updateForm(); } Let us now turn to the TaskEditorTopComponent, which currently cannot be instantiated either with or without a task being provided. You now need to be able to pass a task for initializing the TaskEditorPanel. The new default constructor creates a new task with the support of a chained constructor, and passes this to the former constructor for the remaining initialization of the editor. In addition, it should now be able to return several instances of the TaskEditorTopComponent that are each responsible for a specific task. Hence, the class should be extended by a static method for creating new or finding existing instances. These instances are stored in a Map<Task, TaskEditorTopComponent> which is populated by the former constructor with newly created instances. The method checks whether the map for the given task already stores a responsible instance, and creates a new one if necessary. Additionally, this method registers a Listener on the TaskManager to close the relevant editor for deleting a task. As an instance is now responsible for a particular task this should be able to be queried, so we introduce another appropriate method. Consequently, the changes to the TaskEditorTopComponent looks as follows: private static Map<Task, TaskEditorTopComponent> tcByTask = new HashMap<Task, TaskEditorTopComponent>();public static TaskEditorTopComponent findInstance(Task task) { TaskEditorTopComponent tc = tcByTask.get(task); if (null == tc) { tc = new TaskEditorTopComponent(task); } if (null == taskMgr) { taskMgr = Lookup.getDefault().lookup(TaskManager.class); taskMgr.addPropertyChangeListener(newListenForRemovedNodes()); } return tc;}private class ListenForRemovedNodes implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent arg0) { if (TaskManager.PROP_TASKLIST_REMOVE.equals (arg0.getPropertyName())) { Task task = (Task) arg0.getNewValue(); TaskEditorTopComponent tc = tcByTask.get(task); if (null != tc) { tc.close(); tcByTask.remove(task); } } }}private TaskEditorTopComponent() { this(Lookup.getDefault().lookup(TaskManager.class)); }private TaskEditorTopComponent(TaskManager taskMgr) { this((taskMgr != null) ? taskMgr.createTask() : null); }private TaskEditorTopComponent(Task task) { initComponents();// ... ((TaskEditorPanel) this.jPanel1).updateTask(task); this.ic.add(((TaskEditorPanel) this.jPanel1).task); this.associateLookup(new AbstractLookup(this.ic)); tcByTask.put(task, this); }public String getTaskId() { Task task = ((TaskEditorPanel) this.jPanel1).task; return (null != task) ? task.getId() : ""; } With that our preparations are complete and you can turn to the following discussion on Actions.
Read more
  • 0
  • 0
  • 3230
Modal Close icon
Modal Close icon