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

How-To Tutorials

7018 Articles
article-image-google-guice
Packt
24 Sep 2013
13 min read
Save for later

Google Guice

Packt
24 Sep 2013
13 min read
(For more resources related to this topic, see here.) Structure of flightsweb application Our application has two servlets: IndexServlet, which is a trivial example of forwarding any request, mapped with "/" to index.jsp and FlightServlet, which processes the request using the functionality we developed in the previous section and forwards the response to response.jsp. Here in, we simply declare the FlightEngine and SearchRequest as the class attributes and annotate them with @Inject. FlightSearchFilter is a filter with the only responsibility of validating the request parameters. Index.jsp is the landing page of this application and presents the user with a form to search the flights, and response.jsp is the results page. The flight search form will look as shown in the following screenshot: The search page would subsequently lead to the following result page. In order to build the application, we need to execute the following command in the directory, where the pom.xml file for the project resides: shell> mvn clean package The project for this article being a web application project compiles and assembles a WAR file, flightsweb.war in the target directory. We could deploy this file to TOMCAT. Using GuiceFilter Let's start with a typical web application development scenario. We need to write a JSP to render a form for searching flights and subsequently a response JSP page. The search form would post the request parameters to a processing servlet, which processes the parameters and renders the response. Let's have a look at web.xml. A web.xml file for an application intending to use Guice for dependency injection needs to apply the following filter: <filter> <filter-name>guiceFilter</filter-name> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> It simply says that all the requests need to pass via the Guice filter. This is essential since we need to use various servlet scopes in our application as well as to dispatch various requests to injectable filters and servlets. Rest any other servlet, filter-related declaration could be done programmatically using Guice-provided APIs. Rolling out our ServletContextListener interface Let's move on to another important piece, a servlet context listener for our application. Why do we need a servlet context listener in the first place? A servlet context listener comes into picture once the application is deployed. This event is the best time when we could bind and inject our dependencies. Guice provides an abstract class, which implements ServletContextListener interface. This class basically takes care of initializing the injector once the application is deployed, and destroying it once it is undeployed. Here, we add to the functionality by providing our own configuration for the injector and leave the initialization and destruction part to super class provided by Guice. For accomplishing this, we need to implement the following API in our sub class: protected abstract Injector getInjector(); Let's have a look at how the implementation would look like: package org.packt.web.listener; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; public class FlightServletContextListener extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector( new ServletModule(){ @Override protected void configureServlets() { // overridden method contains various // configurations } }); }} Here, we are returning the instance of injector using the API: public static Injector createInjector(Module... modules) Next, we need to provide a declaration of our custom FlightServletContextListener interface in web.xml: <listener> <listener-class> org.packt.web.listener.FlightServletContextListener </listener-class> </listener> ServletModule – the entry point for configurations In the argument for modules, we provide a reference of an anonymous class, which extends the class ServletModule. A ServletModule class configures the servlets and filters programmatically, which is actually a replacement of declaring the servlet and filters and their corresponding mappings in web.xml. Why do we need to have a replacement of web.xml in the first place? Think of it on different terms. We need to provide a singleton scope to our servlet. We need to use various web scopes like RequestScope, SessionScope, and so on for our classes, such as SearchRequest and SearchResponse. These could not be done simply via declarations in web.xml. A programmatic configuration is far more logical choice for this. Let's have a look at a few configurations we write in our anonymous class extending the ServletModule: new ServletModule(){ @Override protected void configureServlets() { install(new MainModule()); serve("/response").with(FlightServlet.class); serve("/").with(IndexServlet.class); } } A servlet module at first provides a way to install our modules using the install() API. Here, we install MainModule, which is reused from the previous section. Rest all other modules are installed from MainModule. Binding language ServletModule presents APIs, which could be used for configuring filters and servlets. Using these expressive APIs known as EDSL, we could configure the mappings between servlets, filters, and respective URLs. Guice uses an embedded domain specific language or EDSL to help us create bindings simply and readably. We are already using this notation while creating various sort of bindings using the bind() APIs. Readers could refer to the Binder javadoc, where EDSL is discussed with several examples. Mapping servlets Here, following statement maps the /response path in the application to the FlightServlet class's instance: serve("/response").with(FlightServlet.class); serve() returns an instance of ServletKeyBindingBuilder. It provides various APIs, using which we could map a URL to an instance of servlet. This API also has a variable argument, which helps to avoid repetition. For example, in order to map /response as well as /response-quick, both the URLs to FlightServlet.class we could use the following statement: serve("/response","/response-quick").with(FlightServlet.class); serveRegex() is similar to serve(), but accepts the regular expression for URL patterns, rather than concrete URLs. For instance, an easier way to map both of the preceding URL patterns would be using this API: serveRegex("^response").with(FlightServlet.class); ServletKeyBindingBuilder.with() is an overloaded API. Let's have a look at the various signatures. void with(Class<? extends HttpServlet> servletKey); void with(Key<? extends HttpServlet> servletKey); To use the key binding option, we will develop a custom annotation @FlightServe. FlightServlet will be then annotated with it. Following binding maps a URL pattern to a key: serve("/response").with(Key.get(HttpServlet.class, FlightServe.class)); Since this, we need to just declare a binding between @FlightServe and FlightServlet, which will go in modules: bind(HttpServlet.class). annotatedWith(FlightServe.class).to(FlightServlet.class) What is the advantage of binding indirectly using a key? First of all, it is the only way using which we could separate an interface from an implementation. Also it helps us to assign scope as a part of the configuration. A servlet or a filter must be at least in singleton In this case we can assign scope directly in configuration. The option of annotating a filter or a servlet with @Singleton is also available, although. Guice 3.0 provides following overloaded versions, which even facilitate providing initialization parameters and hence provide type safety. void with(HttpServlet servlet); void with(Class<? extends HttpServlet> servletKey, Map<String, String> initParams); void with(Key<? extends HttpServlet> servletKey, Map<String, String> initParams); void with(HttpServlet servlet, Map<String, String> initParams); An important point to be noted here is that ServletModule not only provides a programmatic API to configure the servlets, but also a type-safe idiomatic API to configure the initialization parameters. It is not possible to ensure type safety while declaring the initialization parameters in web.xml. Mapping filters Similar to the servlets, filters could be mapped to URL patterns or regular expressions. Here, the filter() API is used to map a URL pattern to a Filter. For example: filter("/response").through(FlightSearchFilter.class); filter() returns an instance of FilterKeyBindingBuilder. FlightKeyBindingBuilder provides various APIs, using which we can map a URL to an instance of filter. filter() and filterRegex() APIs take exactly the same kind of arguments as serve() and serveRegex() does when it comes to handling the pure URLs or regular expressions. Let's have a look at FilterKeyBindingBuilder.through() APIs. Similar to ServletKeyBindingBuilder.with() it also provides various overloaded versions: void through(Class<? extends Filter> filterKey); void through(Key<? extends Filter> filterKey); Key mapped to a URL, which is then bound via annotation to an implementation could be exemplified as: filter("/response"). through(Key.get(Filter.class,FlightFilter.class)); The binding is done through annotation. Also note, that the filter implementation is deemed as singleton in scope. bind(Filter.class). annotatedWith(FlightFilter.class). to(FlightSearchFilter.class).in(Singleton.class); Guice 3.0 provides following overloaded versions, which even facilitate providing initialization parameters and provide type safety: void through(Filter filter); void through(Class<? extends Filter> filterKey, Map<String, String> initParams); void through(Key<? extends Filter> filterKey, Map<String, String> initParams); void through(Filter filter, Map<String, String> initParams); Again, these type safe APIs provide a better configuration option then declaration driven web.xml. Web scopes Aside from dependency injection and configuration facilities via programmable APIs, Guice provides feature of scoping various classes, depending on their role in the business logic. As we saw, while developing the custom scope, a scope comes into picture during binding phase. Later, when the scope API is invoked, it brings the provider into picture. Actually it is the provider which is the key to the complete implementation of the scope. Same thing applies for the web scope. @RequestScoped Whenever we annotate any class with either of servlet scopes like @RequestScoped or @SessionScoped, call to scope API of these respective APIs are made. This results in eager preparation of the Provider<T> instances. So to harness these providers, we need not configure any type of binding, as these are implicit bindings. We just need to inject these providers where we need the instances of respective types. Let us discuss various examples related to these servlet scopes. Classes scoped to @RequestScoped are instantiated on every request. A typical example would be to instantiate SearchRequest on every request. We need to annotate the SearchRQ with the @RequestScoped. @RequestScoped public class SearchRequest { ……} Next, in FlightServlet we need to inject the implicit provider: @Inject private Provider<SearchRequest> searchRQProvider; The instance could be fetched simply by invoking the .get() API of the provider: SearchRequest searchRequest = searchRQProvider.get(); @SessionScoped The same case goes with @SessionScoped annotation. In FlightSearchFilter, we need an instance of RequestCounter (a class for keeping track of number of requests in a session). This class RequestCounter needs to be annotated with @SessionScoped, and would be fetched in the same way as the SearchRequest. However the Provider takes care to instantiate it on every new session creation: @SessionScoped public class RequestCounter implements Serializable{……} Next, in FlightSearchFilter, we need to inject the implicit provider: @Inject private Provider<RequestCounter> sessionCountProvider; The instance could be fetched simply by invoking the .get() API of the provider. @RequestParameters Guice also provides a @RequestParameters annotation. It could be directly used to inject the request parameters. Let's have a look at an example in FlightSearchFilter. Here, we inject the provider for type Map<String,String[]> in a field: @Inject @RequestParameters private Provider<Map<String, String[]>> reqParamMapProvider; As the provider is bound internally via InternalServletModule (Guice installs this module internally), we can harness the implicit binding and inject the Provider. An important point to be noted over here is that, in case we try to inject the classes annotated with ServletScopes, like @RequestScoped or @SessionScoped, outside of the ServletContext or via a non HTTP request like RPC, Guice throws the following exception: SEVERE: Exception starting filter guiceFilter com.google.inject.ProvisionException: Guice provision errors: Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped object. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request. This happens because the Providers associated with these scopes necessarily work with a ServletContext and hence it could not complete the dependency injection. We need to make sure that our dependencies annotated with ServletScopes come into the picture only when we are in WebScope. Another way in which the scoped dependencies could be made available is by using the injector.getInstance() API. This however requires that we need to inject the injector itself using the @Inject injector in the dependent class. This is however not advisable as it is mixing dependency injection logic with the application logic. We need to avoid this approach. Exercising caution while scoping Our examples illustrate cases where we are injecting the dependencies with narrower scope in the dependencies of wider scope. For example, RequestCounter (which is @SessionScoped) is injected in FlightSearchFilter (which is a singleton). This needs to be very carefully designed, as in when we are absolutely sure that a narrowly scoped dependency should be always present else it would create a problem. It basically results in scope widening, which means that apparently we are widening the scope of SessionScoped objects to that of singleton scoped object, the servlet. If not managed properly, it could result into memory leaks, as the garbage collector could not collect the references to the narrowly scoped objects, which are held in the widely scoped objects. Sometimes this is unavoidable, in such a case we need to make sure we are following two basic rules: Injecting the narrow scoped dependency using Providers. By following this strategy, we never allow the widely scoped class to hold the reference to the narrowly scoped dependency, once it goes out of scope. Do not get the injector instance injected in the wide scoped class instance to fetch the narrow scoped dependency, directly. It could result in hard to debug bugs. Make sure that we use the dependent narrowly scoped objects in APIs only. This lets these to live as stack variables rather than heap variables. Once method execution finishes, the stack variables are garbage collected. Assigning the object fetched from the provider to a class level reference could affect garbage collection adversely, and result in memory leaks. Here, we are using these narrowly scoped dependencies in APIs: doGet() and doFilter(). This makes sure that they are always available. Contrarily, injecting widely scoped dependencies in narrowly scoped dependencies works well, for example, in a @RequestScoped annotated class if we inject a @SessionScoped annotated dependency, it is much better since it is always guaranteed that dependency would be available for injection and once narrowly scoped object goes out of scope it is garbage collected properly. We retrofitted our flight search application in a web environment. In doing so we learned about many aspects of the integration facilities Guice offers us: We learned how to set up the application to use dependency injection using GuiceFilter and a custom ServletContextListener. We saw how to avoid servlet, filter mapping in web.xml, and follow a safer programmatic approach using ServletModule. We saw the usage of various mapping APIs for the same and also certain newly introduced features in Guice 3.0. We discussed how to use the various web scopes.
Read more
  • 0
  • 0
  • 2723

Packt
24 Sep 2013
7 min read
Save for later

Mobiles First – How and Why

Packt
24 Sep 2013
7 min read
(For more resources related to this topic, see here.) What is Responsive Web Design? Responsive Web Design (RWD) is a set of strategies used to display web pages on screens of varying sizes. These strategies leverage, among other things, features available in modern browsers as well as a strategy of progressive enhancement (rather than graceful degradation). What's with all the buzzwords? Well, again, once we dig into the procedures and the code, it will all get a lot more meaningful. But here is a quick example to illustrate a two-way progressive enhancement that is used in RWD. Let's say you want to make a nice button that is a large target and can be reliably pressed with big, fat clumsy thumbs on a wide array of mobile devices. In fact, you want that button to pretty much run the full spectrum of every mobile device known to humans. This is not a problem. The following code is how your (greatly simplified) HTML will look: <!DOCTYPE html> <head> <link rel="stylesheet" href="css/main.css"> </head> <body> <button class="big-button">Click Me!</button> </body> </html> The following code is how your CSS will look: .big-button { width: 100%; padding: 8px 0; background: hotPink; border: 3px dotted purple; font-size: 18px; color: #fff; border-radius: 20px; box-shadow: #111 3px 4px 0px; } So this gets you a button that stretches the width of the document's body. It's also hot pink with a dotted purple border and thick black drop shadow (don't judge my design choices). Here is what is nice about this code. Let's break down the CSS with some imaginary devices/browsers to illustrate some of the buzzwords in the first paragraph of this section: Device one (code name: Goldilocks): This device has a modern browser, with screen dimensions of 320 x 480 px. It is regularly updated, so is highly likely to have all the cool browser features you read about in your favorite blogs. Device two (code name: Baby Bear): This device has a browser that partially supports CSS2 and is poorly documented, so much so that you can only figure out which styles are supported through trial and error or forums. The screen is 320 x 240 px. This describes a device that predated the modern adoption levels of browsing the web on a mobile but your use case may require you to support it anyway. Device three (code name: Papa Bear): This is a laptop computer with a modern browser but you will never know the screen dimensions since the viewport size is controlled by the user. Thus, Goldilocks gets the following display: Because it is all tricked out with full CSS3 feature, it will render the rounded corners and drop shadow. Baby Bear, on the other hand, will only get square corners and no drop shadow (as seen in the previous screenshot) because its browser can't make sense of those style declarations and will just do nothing with them. It's not a huge deal, though, as you still get the important features of the button; it stretches the full width of the screen, making it a big target for all the thumbs in the world (also, it's still pink). Papa Bear gets the button with all the CSS3 goodies too. That said, it stretches the full width of the browser no matter how absurdly wide a user makes his/her browser. We only need it to be about 480 px wide to make it big enough for a user to click and look reasonable within whatever design we are imagining. So in order to make that happen, we will take advantage of a nifty CSS3 feature called @media queries. We will use these extensively throughout this article and make your stylesheet look like this: .big-button { width: 100%; padding: 8px 0; background: hotPink; border: 3px dotted purple; font-size: 18px; color: #fff; border-radius: 20px; box-shadow: #111 3px 3px 0px; } @media only screen and (min-width: 768px){ .big-button { width: 480px; } } Now if you were coding along with me and have a modern browser (meaning a browser that supports most, if not all, features in the HTML5 specification, more on this later), you could do something fun. You can resize the width of your browser to see the start button respond to the @media queries. Start off with the browser really narrow and the button will get wider until the screen is 768 px wide; beyond that the button will snap to being only 480 px. If start off with your browser wider than 768 px, the button will stay 480 px wide until your browser width is under 768 px. Once it is under this threshold, the button snaps to being full width. This happens because of the media query. This query essentially asks the browser a couple of questions. The first part of the query is about what type of medium it is (print or screen). The second part of the query asks what the screen's minimum width is. When the browser replies yes to both screen and min-width 768px, the conditions are met for applying the styles within that media query. To say these styles are applied is a little misleading. In fact, the approach actually takes advantage of the fact that the styles provided in the media query can override other styles set previously in the stylesheet. In our case, the only style applied is an explicit width for the button that overrides the percentage width that was set previously. So, the nice thing about this is, we can make one website that will display appropriately for lots of screen sizes. This approach re-uses a lot of code, only applying styles as needed for various screen widths. Other approaches for getting usable sites to mobile devices require maintaining multiple codebases and having to resort to device detection, which only works if you can actually detect what device is requesting your website. These other approaches can be fragile and also break the Don't Repeat Yourself (DRY) commandment of programming. This article is going to go over a specific way of approaching RWD, though. We will use the 320 and Up framework to facilitate a mobile first strategy. In short, this strategy assumes that a device requesting the site has a small screen and doesn't necessarily have a lot of processing power. 320 and Up also has a lot of great helpers to make it fast and easy to produce features that many clients require on their sites. But we will get into these details as we build a simple site together. Take note, there are lots of frameworks out there that will help you build responsive sites, and there are even some that will help you build a responsive, mobile first site. One thing that distinguishes 320 and Up is that it is a tad less opinionated than most frameworks. I like it because it is simple and eliminates the busy work of setting up things one is likely to use for many sites. I also like that it is open source and can be used with static sites as well as any server-side language. Prerequisites Before we can start building, you need to download the code associated with this article. It will have all the components that you will need and is structured properly for you. If you want 320 and Up for your own projects, you can get it from the website of Andy Clarke (he's the fellow responsible for 320 and Up) or his GitHub account. I also maintain a fork in my own GitHub repo. Andy Clarke's site http://stuffandnonsense.co.uk/projects/320andup/ GitHub https://github.com/malarkey/320andup My GitHub Fork https://github.com/jasongonzales23/320andup That said, the simplest route to follow along with this article is to get the code I've wrapped up for you from: https://github.com/jasongonzales23/mobilefirst_book Summary In this article, we looked at a simple example of how responsive web design strategies can serve up the same content to screens of many sizes and have the layout adjust to the screen it is displayed on. We wrote a simple example of that for a pink button and got a link to 320 and Up, so we can get started building an entire mobile first-responsive website. Resources for Article: Further resources on this subject: HTML5 Canvas [Article] HTML5 Presentations - creating our initial presentation [Article] Creating mobile friendly themes [Article]
Read more
  • 0
  • 0
  • 15271

article-image-applying-webrtc-education-and-e-learning
Packt
24 Sep 2013
3 min read
Save for later

Applying WebRTC for Education and E-learning

Packt
24 Sep 2013
3 min read
(For more resources related to this topic, see here.) The whole education market is currently undergoing yet another revolution as e-learning platforms such as Learning Management System (LMS), e-portfolios, and Massive Online Open Course (MOOC) continue to reshape the whole industry. This has created the perfect fertile ground for the integration of WebRTC. More students and educators are interacting online everyday, but currently this is primarily using standard web page and document-based user interfaces. The only video and audio conferencing options commonly available to educators and students today are those using proprietary systems, such as Skype and Adobe Connect. Each of these solutions requires additional software and often a completely standalone application to be installed. The setup time to establish each of these calls is usually quite high, and some of these solutions also require a licensing fee or setup cost. A recently introduced solution that is gaining quite a bit of attraction in the education and e-learning space is Google Hangouts. Yet, even this requires the download of a proprietary browser plugin and also requires that each participant has an active Google Plus account. With the introduction of WebRTC, it is now possible to skip all of these setup hurdles and seamlessly add video conferencing, screen sharing, and a whole host of other real-time interaction options to the existing web tools that the educators and students are already using. By just adding some simple JavaScript and HTML to their existing web pages, these new interaction options can quickly and easily be introduced. And from the end user's perspective, it couldn't be any simpler. They would just see one or two new buttons appearing on their page, and all they have to do is click on them to start a video call, screen sharing session, or more. There is no more installing of applications or plugins and dealing with the complexity of setting up calls. Summary The education system is changing and with the increasing needs, modern technologies such as video and audio conferencing are of a great help. With introduction of WebRTC, you can seamlessly add video conferencing, screen sharing, and a whole host of other real-time interaction options to the existing web tools that the educators and students are already using. Resources for Article : Further resources on this subject: How to Set Up IBM Lotus Domino Server [Article] So, what is Ext JS? [Article] Ext JS 4: Working with the Grid Component [Article]
Read more
  • 0
  • 0
  • 2314

article-image-making-subtle-color-shifts-curves
Packt
23 Sep 2013
7 min read
Save for later

Making subtle color shifts with curves

Packt
23 Sep 2013
7 min read
(For more resources related to this topic, see here.) When looking at a scene, we may pick up subtle cues from the way colors shift between different image regions. For example, outdoors on a clear day, shadows have a slightly blue tint due to the ambient light reflected from the blue sky, while highlights have a slightly yellow tint because they are in direct sunlight. When we see bluish shadows and yellowish highlights in a photograph, we may get a "warm and sunny" feeling. This effect may be natural, or it may be exaggerated by a filter. Curve filters are useful for this type of manipulation. A curve filter is parameterized by sets of control points. For example, there might be one set of control points for each color channel. Each control point is a pair of numbers representing the input and output values for the given channel. For example, the pair (128, 180) means that a value of 128 in the given color channel is brightened to become a value of 180. Values between the control points are interpolated along a curve (hence the name, curve filter). In Gimp, a curve with the control points (0, 0), (128, 180), and (255, 255) is visualized as shown in the following screenshot: The x axis shows the input values ranging from 0 to 255, while the y axis shows the output values over the same range. Besides showing the curve, the graph shows the line y = x (no change) for comparison. Curvilinear interpolation helps to ensure that color transitions are smooth, not abrupt. Thus, a curve filter makes it relatively easy to create subtle, natural-looking effects. We may define an RGB curve filter in pseudocode as follows: dst.b = funcB(src.b) where funcB interpolates pointsB dst.g = funcG(src.g) where funcG interpolates pointsG dst.r = funcR(src.r) where funcR interpolates pointsR For now, we will work with RGB and RGBA curve filters, and with channel values that range from 0 to 255. If we want such a curve filter to produce natural-looking results, we should use the following rules of thumb: Every set of control points should include (0, 0) and (255, 255). This way, black remains black, white remains white, and the image does not appear to have an overall tint. As the input value increases, the output value should always increase too. (Their relationship should be monotonically increasing.) This way, shadows remain shadows, highlights remain highlights, and the image does not appear to have inconsistent lighting or contrast. OpenCV does not provide curvilinear interpolation functions but the Apache Commons Math library does. (See Adding files to the project, earlier in this chapter, for instructions on setting up Apache Commons Math.) This library provides interfaces called UnivariateInterpolator and UnivariateFunction, which have implementations including LinearInterpolator, SplineInterpolator, LinearFunction, and PolynomialSplineFunction. (Splines are a type of curve.) UnivariateInterpolator has an instance method, interpolate(double[] xval, double[] yval), which takes arrays of input and output values for the control points and returns a UnivariateFunction object. The UnivariateFunction object can provide interpolated values via the method value(double x). API documentation for Apache Commons Math is available at http://commons.apache.org/proper/commons-math/apidocs/. These interpolation functions are computationally expensive. We do not want to run them again and again for every channel of every pixel and every frame. Fortunately, we do not have to. There are only 256 possible input values per channel, so it is practical to precompute all possible output values and store them in a lookup table. For OpenCV's purposes, a lookup table is a Mat object whose indices represent input values and whose elements represent output values. The lookup can be performed using the static method Core.LUT(Mat src, Mat lut, Mat dst). In pseudocode, dst = lut[src]. The number of elements in lut should match the range of values in src, and the number of channels in lut should match the number of channels in src. Now, using Apache Commons Math and OpenCV, let's implement a curve filter for RGBA images with channel values ranging from 0 to 255. Open CurveFilter.java and write the following code: public class CurveFilter implements Filter { // The lookup table. private final Mat mLUT = new MatOfInt(); public CurveFilter( final double[] vValIn, final double[] vValOut, final double[] rValIn, final double[] rValOut, final double[] gValIn, final double[] gValOut, final double[] bValIn, final double[] bValOut) { // Create the interpolation functions. UnivariateFunction vFunc = newFunc(vValIn, vValOut); UnivariateFunction rFunc = newFunc(rValIn, rValOut); UnivariateFunction gFunc = newFunc(gValIn, gValOut); UnivariateFunction bFunc = newFunc(bValIn, bValOut); // Create and populate the lookup table. mLUT.create(256, 1, CvType.CV_8UC4); for (int i = 0; i < 256; i++) { final double v = vFunc.value(i); final double r = rFunc.value(v); final double g = gFunc.value(v); final double b = bFunc.value(v); mLUT.put(i, 0, r, g, b, i); // alpha is unchanged } } @Override public void apply(final Mat src, final Mat dst) { // Apply the lookup table. Core.LUT(src, mLUT, dst); } private UnivariateFunction newFunc(final double[] valIn, final double[] valOut) { UnivariateInterpolator interpolator; if (valIn.length > 2) { interpolator = new SplineInterpolator(); } else { interpolator = new LinearInterpolator(); } return interpolator.interpolate(valIn, valOut); } } CurveFilter stores the lookup table in a member variable. The constructor method populates the lookup table based on the four sets of control points that are taken as arguments. As well as a set of control points for each of the RGB channels, the constructor also takes a set of control points for the image's overall brightness, just for convenience. A helper method, newFunc, creates an appropriate interpolation function (linear or spline) for each set of control points. Then, we iterate over the possible input values and populate the lookup table. The apply method is a one-liner. It simply uses the precomputed lookup table with the given source and destination matrices. CurveFilter can be subclassed to define a filter with a specific set of control points. For example, let's open PortraCurveFilter.java and write the following code: public class PortraCurveFilter extends CurveFilter { public PortraCurveFilter() { super( new double[] { 0, 23, 157, 255 }, // vValIn new double[] { 0, 20, 173, 255 }, // vValOut new double[] { 0, 69, 213, 255 }, // rValIn new double[] { 0, 69, 218, 255 }, // rValOut new double[] { 0, 52, 189, 255 }, // gValIn new double[] { 0, 47, 196, 255 }, // gValOut new double[] { 0, 41, 231, 255 }, // bValIn new double[] { 0, 46, 228, 255 }); // bValOut } } This filter brightens the image, makes shadows cooler (more blue), and makes highlights warmer (more yellow). It produces flattering skin tones and tends to make things look sunnier and cleaner. It resembles the color characteristics of a brand of photo film called Kodak Portra, which was often used for portraits. The code for our other three channel mixing filters is similar. The ProviaCurveFilter class uses the following arguments for its control points: new double[] { 0, 255 }, // vValIn new double[] { 0, 255 }, // vValOut new double[] { 0, 59, 202, 255 }, // rValIn new double[] { 0, 54, 210, 255 }, // rValOut new double[] { 0, 27, 196, 255 }, // gValIn new double[] { 0, 21, 207, 255 }, // gValOut new double[] { 0, 35, 205, 255 }, // bValIn new double[] { 0, 25, 227, 255 }); // bValOut The effect is a strong, blue or greenish-blue tint in shadows and a strong, yellow or greenish-yellow tint in highlights. It resembles a film processing technique called cross-processing, which was sometimes used to produce grungy-looking photos of fashion models, pop stars, and so on. For a good discussion of how to emulate various brands of photo film, see Petteri Sulonen's blog at http://www.prime-junta.net/pont/How_to/100_Curves_and_Films/_Curves_and_films.html. The control points that we use are based on examples given in this article. Curve filters are a convenient tool for manipulating color and contrast, but they are limited insofar as each destination pixel is affected by only a single input pixel. Next, we will examine a more flexible family of filters, which enable each destination pixel to be affected by a neighborhood of input pixels. Summary In this article we learned how to make subtle color shifts with curves. Resources for Article: Further resources on this subject: Linking OpenCV to an iOS project [Article] A quick start – OpenCV fundamentals [Article] OpenCV: Image Processing using Morphological Filters [Article]
Read more
  • 0
  • 0
  • 14268

article-image-game-publishing
Packt
23 Sep 2013
14 min read
Save for later

Game Publishing

Packt
23 Sep 2013
14 min read
(For more resources related to this topic, see here.) Manifest file Many application details are specified in the manifest file. Thus, we will modify it to set the correct application name, description, as well as choose suitable tile images. we can adjust these settings on the Application UI page in the Manifest Designer. Basic configuration As presented in the following screenshot, set the Display Name field to Space Aim 3D, and adjust the Description field as well. What is more, we should choose the suitable App Icon, which is an image with size 100 x 100 pixels. It represents our application, thus we should provide the game with a proper icon that the user can easily recognize. In the exemplary game, the icon shows the planet and a few asteroids, which are the main elements in the game. What is more, the image contains the game title. It is important, because we clear the content of the Tile Title setting. Thus the user will not see additional small text with a name of the application, after pinning the tile to the Start screen. Tiles Apart from some basic settings, we can also choose tile images. They will be shown on the default tile when the player taps the game to the Start screen. we can also create secondary tiles, which could navigate to particular locations inside the application. However, such a solution is not shown in this article. The Windows Phone 8 platform supports three kinds of tile templates: flip, iconic, and cycle. They differ by a way of presenting content. Of course, we can select a suitable one also in the Manifest Designer by choosing an option from the Tile Template list. The flip tile template is the default option, which allows we to present two sides of the tile and flip between them. Thus, we can present the game logo on the front side and some more information on the other side. The tile flips automatically. we can specify settings regarding the background images, titles shown on the front and back sides, the content presented on the other side, as well as the number displayed on the tile. The iconic tile template shows the content in a bit different way. Here, a small icon is used to present the application, together with an optional number, for example, regarding received messages in our project. Of course, we can set some properties, including the tile title, the image, as well as the background color. The cycle tile template is the last available type, which makes it possible to present up to nine images that are changed automatically. Thus, it can be a suitable way to present a tile for the application which works with many images. In case of the cycle tile template, we can also adjust a few settings, such as the title or the shown images. Tiles can be available in three sizes: small (159 x 159 pixels), medium (336 x 336), and large (691 x 336). The small and medium ones are mandatory, while the large one is optional. With the usage of the Manifest Designer, it is very easy to prepare the basic version of the default tile for the application, just by selecting a suitable template type and choosing images which should be shown on the tile, depending on its size. we can also enable or disable the support for a large tile. After adjusting the tiles, we may receive a result as shown in the following screenshot: As we can see, the tile is presented in three various sizes: small, medium, and large. What is important, we do not just rescale the image, but provide three separate images in particular sizes, which look good regardless of the tile size. Here, we can also find the Space Aim 3D shortcut in the application list. However, we can expect that it appears in the Games group instead. Fortunately, we do not need to worry about it, because after downloading the game from the store, its shortcut will be shown in the proper place. As we could remember, the flip data template, which we chose, can present two sides of the tile, but now we do not see this effect. Thus, in the following part of this section we will learn how to configure the default tile to support flipping and how to set the background image and the content at the back. To do so, we should open the WMAppManifest.xml file, but not in the Manifest Designer. we need to choose the View Code option from the context menu of this file. What is interesting, the XML code contains information that we had set in a graphical way. Thus, it can be an additional way of adjusting some settings and adding more complex features, which are not supported directly by the Manifest Designer. The TemplateFlip node, specified in the WMAppManifest.xml file, is as follows: <TemplateFlip> <SmallImageURI (...)> (...) </SmallImageURI> <Count>0</Count> <BackgroundImageURI (...)> (...) </BackgroundImageURI> <Title></Title> <BackContent>Let's avoid asteroids and reach the target planet!</BackContent> <BackBackgroundImageURI></BackBackgroundImageURI> <BackTitle>Space Aim 3D</BackTitle> <LargeBackgroundImageURI (...)> (...) </LargeBackgroundImageURI> <LargeBackContent>Let's avoid asteroids, reach the target planet, and see players in the vicinity!</LargeBackContent> <LargeBackBackgroundImageURI(...)></LargeBackBackgroundImageURI> <DeviceLockImageURI></DeviceLockImageURI> <HasLarge>True</HasLarge> </TemplateFlip> Here, we specify the BackContent, BackTitle, and LargeBackContent elements to adjust a way of presenting the back side of the tile. The first setting is a string which will be displayed on the other side of the medium-sized tile. The second setting is the title shown on the back side (regardless of the tile size), while the other is a string shown on the large tile. When we deploy the application to the emulator or the phone, and tap it to the start screen, we should see that the tile flips automatically, and it should present some additional content on the back side. What is more, it differs depending on the tile size, as shown in the following screenshots: The Windows Phone 8 platform also supports live tiles, which present the content received from the Internet and are updated automatically. Such a kind of tiles can use either the push notifications or the local notifications. Remaining settings we have completed the basic configuration of the application, as well as learned how to set up the default tile. However, a few other modifications are necessary on the Packaging tab. Here, we specify the author and publisher data, as well as a version of the application. Other tabs (Capabilities and Requirements) remain unchanged, because we made the required modifications earlier. Rating by the users While designing the web screen, we created the button which should allow the user to rate the game. we can easily implement this functionality with the MarketplaceReviewTask class, which is another launcher used in the exemplary game. we need to modify the Rate method of the webViewModel class, as shown in the following code snippet: private void Rate() { MarketplaceReviewTask task = new MarketplaceReviewTask(); task.Show(); } Here, we create a new instance of the MarketplaceReviewTask class (from the Microsoft.Phone.Tasks namespace) and call the Show method. When this part of code is executed, the review page is opened, where the user can rate and review the current application. Release version The development environment for programming the Windows Phone 8 applications is equipped with many advanced features regarding their debugging. Such functionalities may require a bit different form of the code, which can be executed slower, but provide the developers with additional possibilities during development. For this reason, it is important to prepare the release version (retail) of the game before publishing. we can easily generate the release version of the .xap file (with the data of wer application) using the IDE. To do it, we should change two options located next to the green triangle, and a selection of the emulator or device, as shown in the following screenshot. Here, we should indicate that we want to use the Release mode, as well as the ARM platform. Then, we should select Build and Rebuild Solution options to generate the suitable version of the .xap file. Now, we can proceed to the process of testing our game and preparing for submission to the store! Store Test Kit Some testing operations are simplified by the Store Test Kit, which allows to perform a set of automatic and manual tests. They can be used to verify many requirements that should be met to accept the application in the store. we can open the tool by choosing the Open Store Test Kit option from the context menu of the SpaceAim3D project (not solution), or by choosing the Open Store Test Kit entry from the Project menu. The tool contains three pages: Application Details, Automated Tests, and Manual Tests. we will learn how to use all of them in this section. Application details In the first page we should specify some details regarding the application, including the store tile image with size 300 x 300 pixels. Apart from it, we need to choose a set of screenshots for each supported screen resolution. It is important to add at least one screenshot and not more than eight. Each of them should be provided in proper resolution, that is, 480 x 800 (WVGA), 768 x 1280 (WXGA), and 720 x 1280 (720P). The Application Details page is shown in the following screenshot: In case of applications running in the landscape mode (as in case of wer game), we should provide images that are not rotated, that is, as captured in the emulator. we can make screenshots either in the emulator (using the Screenshot tab in the Additional Tools window) or on the phone. In the latter case, we should press the Start and power buttons. When a screenshot is taken correctly, a shutter sound is played and the image is saved in a suitable album. The Application Package field is a read-only textbox, where a path to the .xap file is shown. It is worth mentioning that it indicates the Release version for ARM, thus it is exactly the same version as we generated earlier. Automated tests The second page is named Automated Tests. By clicking on the Run Tests button, we run a basic verification of wer project regarding the submission requirements, for example, whether the .xap file size is correct, as well as we provide the suitable icons and screenshots. If all tests are passed, we will receive a result as shown in the following screenshot. Otherwise, some additional notes are shown. In such a situation, we need to fix errors and run the tests once again. It is important to note that passing all automated tests does not mean that the application does not contain any errors which could prevent the project from being accepted in the store. Manual tests Additional verification can be performed manually, by using the Manual Tests tab in the Store Test Kit. Here, we have a list of test cases and their descriptions. we should follow them and manually indicate whether the test is passed or failed as shown in the following screenshot: Simulation Dashboard The exemplary game may be used in various conditions, often significantly different than our testing environment. For instance, the player can have a limited access to the Internet or switched off the location services. For this reason, we should try to test our project in many situations. Such a process can be simplified by the Simulation Dashboard tool. we can open it by choosing the Simulation Dashboard option from the Tools menu. Its window is shown in the following screenshot: This tool makes it possible to simulate some specific network conditions, by choosing a proper network speed and signal strength. we can choose 2G, 3G, 4G, Wi-Fi, and No Network options as the speed, as well as Good, Average, and Poor as the Signal Strength. Thus, we can check how our application behaves if we need to download some data from the Internet using the slower network connection, or even whether the game responds correctly in case of no network access. Apart from the network simulation, the Simulation Dashboard allows we to lock and unlock the screen just by choosing a suitable option from the Lock Screen group. The last supported testing feature is named Reminders. Just after pressing the Trigger Reminder button, the reminder is shown in the emulator. Thus, we can easily check how wer application reacts in such a situation. Windows Phone Application Analysis Apart from testing the project in real-world conditions, it is important to check its performance and try to eliminate problems in this area. Fortunately, the Windows Phone Application Analysis tool is integrated with the IDE, and we can use it to measure the performance of various parts of our game. The tool can be started by selecting the Start Windows Phone Application Analysis option from the Debug menu. After launching, we should have the Execution option selected, thus we can click on the Start Session (App will start) element. It automatically starts our game in the emulator, if it is selected as the target. Then, a process of collecting data is started, and we can use the application in various ways to check the performance of its several areas. For instance, we can start by spending some time on the Menu screen, then we launch the game and play ten levels, return to the menu, and open additional screens (such as Ranks, Map, or World). When we want to finish collecting performance data, we should click on the End Session (App will exit) option. Then, the process of collecting data stops and the report is created, which can take some time. The .sap file is generated for each analysis session. It is saved in the directory of the managed project, and can be later opened and analyzed using the IDE. The Windows Phone Application Analysis tool presents a lot of important data related to the game performance, including both the managed and the native parts. The graph, presented in the main part of the window, shows the CPU usage at a particular time, as shown in the following screenshot. we can easily analyze which part of our application causes performance issues, and we may try to improve them. As we can see in the preceding screenshot, the performance results for the Space Aim 3D game are expectable and reasonable. In case of the Menu screen, the CPU usage is very low. It grows significantly for the Game page, but here we need to perform a lot of operations, for example, related to rendering many objects in the 3D game world. What is interesting, the CPU usage grows slightly while consecutive levels, but also on the tenth level, the game works smoothly both in the emulator and on the phone. As soon as we exit to the main menu, the CPU usage decreases almost immediately. The remaining part is related to opening the following game screens: Ranks, Map, World, and others. The possibilities of the Windows Phone Application Analysis are not limited only to drawing the graph of the CPU usage. we can also see the Hot Path information, which lets us know what part of code uses the most processing power. In our case, it is the region that renders 3D objects on the screen, using Direct3D. What is more, we can click on a name of the particular function to open another view, which shows more details. By using the tool, we can even analyze the performance of particular lines of code, as shown in the following screenshot: Available features make it significantly easier to find a bottleneck causing performance problems. By running the Windows Phone Application Analysis tool multiple times, while making modifications in the code, we can see how wer changes reflect in the performance.
Read more
  • 0
  • 0
  • 1856

article-image-eventbus-class
Packt
23 Sep 2013
14 min read
Save for later

The EventBus Class

Packt
23 Sep 2013
14 min read
(For more resources related to this topic, see here.) When developing software, the idea of objects sharing information or collaborating with each other is a must. The difficulty lies in ensuring that communication between objects is done effectively, but not at the cost of having highly coupled components. Objects are considered highly coupled when they have too much detail about other components' responsibilities. When we have high coupling in an application, maintenance becomes very challenging, as any change can have a rippling effect. To help us cope with this software design issue; we have event-based programming. In event-based programming, objects can either subscribe/listen for specific events, or publish events to be consumed. In Java, we have had the idea of event listeners for some time. An event listener is an object whose purpose is to be notified when a specific event occurs. In this article, we are going to discuss the Guava EventBus class and how it facilitates the publishing and subscribing of events. The EventBus class will allow us to achieve the level of collaboration we desire, while doing so in a manner that results in virtually no coupling between objects. It's worth noting that the EventBus is a lightweight, in-process publish/subscribe style of communication, and is not meant for inter-process communication. We are going to cover several classes in this article that have an @Beta annotation indicating that the functionality of the class may be subject to change in future releases of Guava. EventBus The EventBus class (found in the com.google.common.eventbus package) is the focal point for establishing the publish/subscribe-programming paradigm with Guava. At a very high level, subscribers will register with EventBus to be notified of particular events, and publishers will send events to EventBus for distribution to interested subscribers. All the subscribers are notified serially, so it's important that any code performed in the event-handling method executes quickly. Creating an EventBus instance Creating an EventBus instance is accomplished by merely making a call to the EventBus constructor: EventBus eventBus = new EventBus(); We could also provide an optional string argument to create an identifier (for logging purposes) for EventBus: EventBus eventBus = new EventBus(TradeAccountEvent.class.getName()); Subscribing to events The following three steps are required by an object to receive notifications from EventBus,: The object needs to define a public method that accepts only one argument. The argument should be of the event type for which the object is interested in receiving notifications. The method exposed for an event notification is annotated with an @Subscribe annotation. Finally, the object registers with an instance of EventBus, passing itself as an argument to the EventBus.register method. Posting the events To post an event, we need to pass an event object to the EventBus.post method. EventBus will call the registered subscriber handler methods, taking arguments those are assignable to the event object type. This is a very powerful concept because interfaces, superclasses, and interfaces implemented by superclasses are included, meaning we can easily make our event handlers as course- or fine-grained as we want, simply by changing the type accepted by the event-handling method. Defining handler methods Methods used as event handlers must accept only one argument, the event object. As mentioned before, EventBus will call event-handling methods serially, so it's important that those methods complete quickly. If any extended processing needs to be done as a result of receiving an event, it's best to run that code in a separate thread. Concurrency EventBus will not call the handler methods from multiple threads, unless the handler method is marked with the @AllowConcurrentEvent annotation. By marking a handler method with the @AllowConcurrentEvent annotation, we are asserting that our handler method is thread-safe. Annotating a handler method with the @AllowConcurrentEvent annotation by itself will not register a method with EventBus. Now that we have defined how we can use EventBus, let's look at some examples. Subscribe – An example Let's assume we have defined the following TradeAccountEvent class as follows: public class TradeAccountEvent { private double amount; private Date tradeExecutionTime; private TradeType tradeType; private TradeAccount tradeAccount; public TradeAccountEvent(TradeAccount account, double amount, Date tradeExecutionTime, TradeType tradeType) { checkArgument(amount > 0.0, "Trade can't be less than zero"); this.amount = amount; this.tradeExecutionTime = checkNotNull(tradeExecutionTime,"ExecutionTime can't be null"); this.tradeAccount = checkNotNull(account,"Account can't be null"); this.tradeType = checkNotNull(tradeType,"TradeType can't be null"); } //Details left out for clarity So whenever a buy or sell transaction is executed, we will create an instance of the TradeAccountEvent class. Now let's assume we have a need to audit the trades as they are being executed, so we have the SimpleTradeAuditor class as follows: public class SimpleTradeAuditor { private List<TradeAccountEvent> tradeEvents = Lists.newArrayList(); public SimpleTradeAuditor(EventBus eventBus){ eventBus.register(this); } @Subscribe public void auditTrade(TradeAccountEvent tradeAccountEvent){ tradeEvents.add(tradeAccountEvent); System.out.println("Received trade "+tradeAccountEvent); } } Let's quickly walk through what is happening here. In the constructor, we are receiving an instance of an EventBus class and immediately register the SimpleTradeAuditor class with the EventBus instance to receive notifications on TradeAccountEvents. We have designated auditTrade as the event-handling method by placing the @Subscribe annotation on the method. In this case, we are simply adding the TradeAccountEvent object to a list and printing out to the console acknowledgement that we received the trade. Event Publishing – An example Now let's take a look at a simple event publishing example. For executing our trades, we have the following class: public class SimpleTradeExecutor { private EventBus eventBus; public SimpleTradeExecutor(EventBus eventBus) { this.eventBus = eventBus; } public void executeTrade(TradeAccount tradeAccount, double amount, TradeType tradeType){ TradeAccountEvent tradeAccountEvent = processTrade(tradeAccount, amount, tradeType); eventBus.post(tradeAccountEvent); } private TradeAccountEvent processTrade(TradeAccount tradeAccount, double amount, TradeType tradeType){ Date executionTime = new Date(); String message = String.format("Processed trade for %s of amount %n type %s @ %s",tradeAccount,amount,tradeType,executionTime); TradeAccountEvent tradeAccountEvent = new TradeAccountEvent(tradeAccount,amount,executionTime,tradeType); System.out.println(message); return tradeAccountEvent; } } Like the SimpleTradeAuditor class, we are taking an instance of the EventBus class in the SimpleTradeExecutor constructor. But unlike the SimpleTradeAuditor class, we are storing a reference to the EventBus for later use. While this may seem obvious to most, it is critical for the same instance to be passed to both classes. We will see in future examples how to use multiple EventBus instances, but in this case, we are using a single instance. Our SimpleTradeExecutor class has one public method, executeTrade, which accepts all of the required information to process a trade in our simple example. In this case, we call the processTrade method, passing along the required information and printing to the console that our trade was executed, then returning a TradeAccountEvent instance. Once the processTrade method completes, we make a call to EventBus.post with the returned TradeAccountEvent instance, which will notify any subscribers of the TradeAccountEvent object. If we take a quick view of both our publishing and subscribing examples, we see that although both classes participate in the sharing of required information, neither has any knowledge of the other. Finer-grained subscribing We have just seen examples on publishing and subscribing using the EventBus class. If we recall, EventBus publishes events based on the type accepted by the subscribed method. This gives us some flexibility to send events to different subscribers by type. For example, let's say we want to audit the buy and sell trades separately. First, let's create two separate types of events: public class SellEvent extends TradeAccountEvent { public SellEvent(TradeAccount tradeAccount, double amount, Date tradExecutionTime) { super(tradeAccount, amount, tradExecutionTime, TradeType.SELL); } } public class BuyEvent extends TradeAccountEvent { public BuyEvent(TradeAccount tradeAccount, double amount, Date tradExecutionTime) { super(tradeAccount, amount, tradExecutionTime, TradeType.BUY); } } Now we have created two discrete event classes, SellEvent and BuyEvent, both of which extend the TradeAccountEvent class. To enable separate auditing, we will first create a class for auditing SellEvent instances: public class TradeSellAuditor { private List<SellEvent> sellEvents = Lists.newArrayList(); public TradeSellAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditSell(SellEvent sellEvent){ sellEvents.add(sellEvent); System.out.println("Received SellEvent "+sellEvent); } public List<SellEvent> getSellEvents() { return sellEvents; } } Here we see functionality that is very similar to the SimpleTradeAuditor class with the exception that this class will only receive the SellEvent instances. Then we will create a class for auditing only the BuyEvent instances: public class TradeBuyAuditor { private List<BuyEvent> buyEvents = Lists.newArrayList(); public TradeBuyAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditBuy(BuyEvent buyEvent){ buyEvents.add(buyEvent); System.out.println("Received TradeBuyEvent "+buyEvent); } public List<BuyEvent> getBuyEvents() { return buyEvents; } } Now we just need to refactor our SimpleTradeExecutor class to create the correct TradeAccountEvent instance class based on whether it's a buy or sell transaction: public class BuySellTradeExecutor { … deatails left out for clarity same as SimpleTradeExecutor //The executeTrade() method is unchanged from SimpleTradeExecutor private TradeAccountEvent processTrade(TradeAccount tradeAccount, double amount, TradeType tradeType) { Date executionTime = new Date(); String message = String.format("Processed trade for %s of amount %n type %s @ %s", tradeAccount, amount, tradeType, executionTime); TradeAccountEvent tradeAccountEvent; if (tradeType.equals(TradeType.BUY)) { tradeAccountEvent = new BuyEvent(tradeAccount, amount, executionTime); } else { tradeAccountEvent = new SellEvent(tradeAccount, amount, executionTime); } System.out.println(message); return tradeAccountEvent; } } Here we've created a new BuySellTradeExecutor class that behaves in the exact same manner as our SimpleTradeExecutor class, with the exception that depending on the type of transaction, we create either a BuyEvent or SellEvent instance. However, the EventBus class is completely unaware of any of these changes. We have registered different subscribers and we are posting different events, but these changes are transparent to the EventBus instance. Also, take note that we did not have to create separate classes for the notification of events. Our SimpleTradeAuditor class would have continued to receive the events as they occurred. If we wanted to do separate processing depending on the type of event, we could simply add a check for the type of event. Finally, if needed, we could also have a class that has multiple subscribe methods defined: public class AllTradesAuditor { private List<BuyEvent> buyEvents = Lists.newArrayList(); private List<SellEvent> sellEvents = Lists.newArrayList(); public AllTradesAuditor(EventBus eventBus) { eventBus.register(this); } @Subscribe public void auditSell(SellEvent sellEvent){ sellEvents.add(sellEvent); System.out.println("Received TradeSellEvent "+sellEvent); } @Subscribe public void auditBuy(BuyEvent buyEvent){ buyEvents.add(buyEvent); System.out.println("Received TradeBuyEvent "+buyEvent); } } Here we've created a class with two event-handling methods. The AllTradesAuditor method will receive notifications about all trade events; it's just a matter of which method gets called by EventBus depending on the type of event. Taken to an extreme, we could create an event handling method that accepts a type of Object, as Object is an actual class (the base class for all other objects in Java), and we could receive notifications on any and all events processed by EventBus. Finally, there is nothing preventing us from having more than one EventBus instance. If we were to refactor the BuySellTradeExecutor class into two separate classes, we could inject a separate EventBus instance into each class. Then it would be a matter of injecting the correct EventBus instance into the auditing classes, and we could have complete event publishing-subscribing independence. Unsubscribing to events Just as we want to subscribe to events, it may be desirable at some point to turn off the receiving of events. This is accomplished by passing the subscribed object to the eventBus.unregister method. For example, if we know at some point that we would want to stop processing events, we could add the following method to our subscribing class: public void unregister(){ this.eventBus.unregister(this); } Once this method is called, that particular instance will stop receiving events for whatever it had previously registered for. Other instances that are registered for the same event will continue to receive notifications. AsyncEventBus We stated earlier the importance of ensuring that our event-handling methods keep the processing light due to the fact that the EventBus processes all events in a serial fashion. However, we have another option with the AsyncEventBus class. The AsyncEventBus class offers the exact same functionality as the EventBus, but uses a provided java.util.concurrent.Executor instance to execute handler methods asynchronously. Creating an AsyncEventBus instance We create an AsyncEventBus instance in a manner similar to the EventBus instance: AsyncEventBus asyncEventBus = new AsyncEventBus(executorService); Here we are creating an AsyncEventBus instance by providing a previously created ExecutorService instance. We also have the option of providing a String identifier in addition to the ExecutorService instance. AsyncEventBus is very helpful to use in situations where we suspect the subscribers are performing heavy processing when events are received. DeadEvents When EventBus receives a notification of an event through the post method, and there are no registered subscribers, the event is wrapped in an instance of a DeadEvent class. Having a class that subscribes for DeadEvent instances can be very helpful when trying to ensure that all events have registered subscribers. The DeadEvent class exposes a getEvent method that can be used to inspect the original event that was undelivered. For example, we could provide a very simple class, which is shown as follows: public class DeadEventSubscriber { private static final Logger logger = Logger.getLogger(DeadEventSubscriber.class); public DeadEventSubscriber(EventBus eventBus) { eventBus.register(this); } @Subscribe public void handleUnsubscribedEvent(DeadEvent deadEvent){ logger.warn("No subscribers for "+deadEvent.getEvent()); } } Here we are simply registering for any DeadEvent instances and logging a warning for the original unclaimed event. Dependency injection To ensure we have registered our subscribers and publishers with the same instance of an EventBus class, using a dependency injection framework (Spring or Guice) makes a lot of sense. In the following example, we will show how to use the Spring Framework Java configuration with the SimpleTradeAuditor and SimpleTradeExecutor classes. First, we need to make the following changes to the SimpleTradeAuditor and SimpleTradeExecutor classes: @Component public class SimpleTradeExecutor { private EventBus eventBus; @Autowired public SimpleTradeExecutor(EventBus eventBus) { this.eventBus = checkNotNull(eventBus, "EventBus can't be null"); } @Component public class SimpleTradeAuditor { private List<TradeAccountEvent> tradeEvents = Lists.newArrayList(); @Autowired public SimpleTradeAuditor(EventBus eventBus){ checkNotNull(eventBus,"EventBus can't be null"); eventBus.register(this); } Here we've simply added an @Component annotation at the class level for both the classes. This is done to enable Spring to pick these classes as beans, which we want to inject. In this case, we want to use constructor injection, so we added an @Autowired annotation to the constructor for each class. Having the @Autowired annotation tells Spring to inject an instance of an EventBus class into the constructor for both objects. Finally, we have our configuration class that instructs the Spring Framework where to look for components to wire up with the beans defined in the configuration class. @Configuration @ComponentScan(basePackages = {"bbejeck.guava.article7.publisher", "bbejeck.guava.article7.subscriber"}) public class EventBusConfig { @Bean public EventBus eventBus() { return new EventBus(); } } Here we have the @Configuration annotation, which identifies this class to Spring as a Context that contains the beans to be created and injected if need be. We defined the eventBus method that constructs and returns an instance of an EventBus class, which is injected into other objects. In this case, since we placed the @Autowired annotation on the constructors of the SimpleTradeAuditor and SimpleTradeExecutor classes, Spring will inject the same EventBus instance into both classes, which is exactly what we want to do. While a full discussion of how the Spring Framework functions is beyond the scope of this book, it is worth noting that Spring creates singletons by default, which is exactly what we want here. As we can see, using a dependency injection framework can go a long way in ensuring that our event-based system is configured properly. Summary In this article, we have covered how to use event-based programing to reduce coupling in our code by using the Guava EventBus class. We covered how to create an EventBus instance and register subscribers and publishers. We also explored the powerful concept of using types to register what events we are interested in receiving. We learned about the AsyncEventBus class, which allows us to dispatch events asynchronously. We saw how we can use the DeadEvent class to ensure we have subscribers for all of our events. Finally, we saw how we can use dependency injection to ease the setup of our event-based system. In the next article, we will take a look at working with files in Guava. Resources for Article: Further resources on this subject: WordPress: Avoiding the Black Hat Techniques [Article] So, what is Google Drive? [Article] Showing your Google calendar on your Joomla! site using GCalendar [Article]
Read more
  • 0
  • 0
  • 3664
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-designing-pages
Packt
23 Sep 2013
15 min read
Save for later

Designing Pages

Packt
23 Sep 2013
15 min read
(For more resources related to this topic, see here.) Microsoft announced a three-tier RoleTailored client (RTC) with Version 2009. As from Version 2013, Microsoft offers only three-tier RTC with NAV. In RTC, the object of type "FORM" is replaced by "PAGE". Pages provide the core way to interact with an NAV RoleTailored client. The business logic called by the page is executed on the NAV Server tier, whereas previously, the form was used by the client system to execute the business logic. A page and form share lots of similarities in terms of properties, triggers, and controls. Some controls and features are reintroduced with a new presentation style and name. For example, "buttons" become "actions", "Tab Control" becomes "FastTabs", and "Zoom" is known as "About this Page". The following screenshot will help you to understand new naming conventions of page controls: The preceding screenshot is of the Role Center page for the Sales Order Processor profile. With NAV 2013, we received 21 profiles and 21 Role Center pages, designed considering each profile work area. The following screenshot also gives additional information about the same profile: Updating the subform page from a parent page The subform page only reloads data when it knows it needs to. Unfortunately, it is not very smart. This recipe will show you how to force a subform page to refresh itself. How to do it... Create a new page from Object Designer. Choose the Create Blank Page option to design a page from scratch. Add the following global variables to the page: Name Type A Integer B Integer Next, add a global function called SetValues. Add the following parameters to the function: Name Type Aparam Integer Bparam Integer Now add the following code to the function. A := Aparam; B := Bparam; Add another global function called UpdateSelf. Then add the following code to the function: CurrPage.UPDATE; From the Page Designer window, set the following page property (Shift+ F4): Property Value PageType CardPart Add the following variables in the Page Designer window: Type SubType SourceExpr Name Container ContentArea   MainContainer Group Group   MainGroup Field   A+B Sum of A & B After the previous configuration and coding, Page Designer will look similar to the following screenshot: Save and close the page (for later use, remember the ID it is saved under). Now let's create another new page using Object Designer. Then add the following global variables: Name Type A Integer B Integer Later, add the following variables in the Page Designer window: Type SubType SourceExpr Name Container ContentArea   MainContainer Group Group   MainGroup Field   A Value For A Field   B Value For B Part Page   ChildPage Make sure all controls are indented under Container as shown in the following screenshot: Next, in the OnValidate trigger for each field, add the following code: CurrPage.ChildPage.PAGE.SetValues(A,B); CurrPage.ChildPage.PAGE.UpdateSelf; In the next row, add the value Part for the column Type, and for the column SubType add value as Page. Set the following properties for the Part section (Shift+ F4): Property Value Name ChildPage PagePartID The ID of the page you just created Finally save and close the page. On execution of the page, you will see a window similar to the following screenshot: How it works... To understand the concepts behind this recipe, we will use the following figure: The main page knows only about things that are directly on itself, that is, two integer variables and a subform page. The main page can request the subform page to return some values and can also tell the subform page to set values if it needs to, but it cannot do it directly. The subform page can only be of type CardPart or ListPart. Also, the subform page knows only about things that are on its own page. These include the two integer variables (completely different than the two integer variables on the main page), the SetValues function, and the UpdateSelf function. While the main page can request information from the subform page, the opposite does not hold true. The subform page knows nothing about the main page. That explains why we add code where we do. For the subform page to display the sum of A and B, we have to tell it what the values of A and B are. Remember that just changing the values on the main page is not enough. That's why we have the SetValues function. We call this function every time the values are changed (OnValidate) in the main form. That again is not enough, though. Just because the values have changed in the subform page, it doesn't mean the subform page is smart enough to understand that it must display the new information. Ordinarily, you would have to click on the subform page (or select it; you can do anything that makes it the active control on the page) for it to refresh. You can also do this with code, using the CurrPage.UPDATE command. Creating a FactBox page In RTC, we can see small boxes on the right-hand side of the pages, which display brief information about the current record. To maintain the standard NAV GUI in customized pages, it is suggested to add FactBox related to the pages. In this recipe, we will create a FactBox page based on Item table and add it on the default Item List page. How to do it... Create a new page from Object Designer. Leave the Table Name field blank and choose the Create Blank Page option to design a page from scratch. From the Page Designer window, set the following page properties (Shift+ F4): Property Value PageType CardPart SourceTable Item Add the following variables in the Page Designer window: Type SubType SourceExpr Name Container ContentArea   MainContainer Field   "No." <No.> Field   Description <Description> Field   Inventory <Inventory> The indented Page Designer window will look similar to the following screenshot: Save and close the page (for later use, remember the ID it is saved under). Choose page 31(Item List) in Object Designer and click on the Design button. At the end of Page Designer, under FactBoxArea, add a new Part of type Page. Now set the following properties for Part (Shift+ F4): Property Value PagePartID The ID of the page you just created SubPageLink No.=FIELD(No.) To adjust the sequence of FactBoxes, use the up and down arrow buttons. Save, close, and run the page. You should find your FactBox in the Item List page. How it works... FactBox is nothing but a subform page; that's why the page type has to be a CardPart or ListPart page. We have created our page based on the Item table with three simple fields. As we are assigning the Inventory field directly to a control, even though it is of type flowfield, we do not need to explicitly calculate it using CALCFIELD. To use our new subform page as FactBox, it's important to add it under a container of type FactBoxArea. To set the first position (by default), we used indentation buttons. Users can use the personalization functionality of RTC and rearrange the position of FactBox as per their convenience. To associate the FactBox data with the main page's record, we need to set up the relation between the main page and the FactBox page. To achieve this, we used the SubPageLink property. If we do not set this property, we will see that of all the item records, FactBox displays information of only the first record. There's more... Microsoft suggests using the word "FactBox" as a suffix for all the FactBox pages. It will help to identify these pages easily. See also Creating a Queue page Creating a Role Center page Creating a Queue page The Queue page is a part of the Role Center page. This recipe will help us to create a Queue page, which we will be utilizing in our next recipe, Creating a Role Center page. How to do it... Create a new blank page from Object Designer. Set the properties of the page as follows: Property Value Caption Activities PageType CardPart SourceTable Sales Cue Add the following variables in the Page Designer window: Type SubType SourceExpr Name Caption Container ContentArea   MainContainer <MainContainer> Group CueGroup   ForReleaseGroup For Release Field   "Sales Quotes - Open" OpenQuotes Open Sales Quotes Field   "Sales Orders - Open" OpenOrders Open Sales Orders Set the following property in the OpenQuotes line: Property Value DrillDownPageID Sales Quotes Set the following property in the OpenOrders line: Property Value DrillDownPageID Sales List After the previous configuration and coding, our page should look similar to the following screenshot: Keep the cursor on the ForReleaseGroup line and navigate to View | Control Actions. Then add the following variables: Type Name Caption Action Action1 New Sales Quote Action Action2 New Sales Order Set the following property in the New Sales Quote line: Property Value RunObject Page Sales Quotes Set the following property in the New Sales Order line: Property Value RunObject Page Sales Order Compile, save, and close the page. When you run the page, you will see a window similar to the following screenshot: How it works... The first part of the Role Center is known as activities. This is where the users look to know what actions they need to perform. The activities are built on top of special tables known as cues. These cue tables are made mostly of FlowFields and FlowFilters. We are going to build our activities part on the Sales Cue table. It should display any Open Sales documents we are working on. By adding the Group line to our page and specifying SubType as CueGroup, we tell the RTC to display the fields indented beneath it in a specific way. Activities are displayed as stacks of paper that grow and shrink based on the numbers returned by the FlowFields in the cue table. Additionally, in order to provide the same type of data access that you would gain on a form, we specify DrillDownFormID for each of the fields or activities. We can also define actions on our group lines. In this example we have created simple links to create new sales quotes and sales orders. See also Creating a FactBox page Creating a Role Center page Adding a chart to the page Creating a Role Center page The Role Center is like a dashboard that displays data and functionality related to a specific user role. This recipe will show you how to create a Role Center page for the new RTC. How to do it... Create a new page from Object Designer. Set the properties of the page as follows: Property Value PageType RoleCenter Add the following variables in the Page Designer window: Type SubType SourceExpr Name Container RoleCenterArea   Content Group Group   LeftSide Part Page   Activities Part System   Outlook Group Group   RightSide Part Page   MyCustomers Part Page   MyItems Part System   MyNotes All of the previous lines should be indented as shown in the following screenshot: Now set the following properties in the Activities line Property Value PartType Page PagePartID The Queue ID of the Activities page that we created in the previous recipe Then set the following properties in the Outlook line: Property Value PartType System SystemPartID Outlook Set the following properties in the MyCustomers line: Property Value PartType Page PagePartID My Customers Set the following properties in the MyItems line: Property Value PartType Page PagePartID My Items Set the following properties in the MyNotes line: Property Value PartType System SystemPartID Notes Compile, save, and close the page. The resulting Role Center should look similar to the one shown in the following screenshot: How it works... We begin with a container, but this time we set the SubType field to RoleCenterArea. This essentially divides the page vertically into a left and right section. We add groups for each of these sections and then choose what to display. Deciding what to display is fairly straightforward. Instead of adding fields to our group, we add parts. First we choose what type of part will be shown. For our activities, this will be a Page object, so we set the PartType property to Page and PagePartID to the object ID of the page. Directly beneath that part, we are displaying the built-in Outlook part. For this, we set the PartType property to System, because it comes with NAV, and the SystemPartID property to Outlook. The right-hand side is made up of similar parts. For more details on the PartType option, visit the following URL: http://msdn.microsoft.com/en-us/library/dd355029(v=nav.70).aspx See also Creating a FactBox page Creating a Queue page Creating a wizard page A wizard is a page that takes you through specific sections using the Next and Back buttons. Here we will show you how to design a page that will do exactly that. How to do it... Create a new blank page from Object Designer. Set the properties of the page as follows: Property Value PageType NavigatePage Create the following global variables: Name Type Length FullName Text 200 Address Text 200 DateofBirth Date   ContactNo Text 30 BackEnable Boolean   NextEnable Boolean   FinishEnable Boolean   Step1Visible Boolean   Step2Visible Boolean   Step3Visible Boolean   Step4Visible Boolean   Add the following variables in Page Designer: Type SubType SourceExpr Name Container ContentArea   Content Group Group   Step1 Field   FullName Enter Your Full Name Group Group   Step2 Field   Address Enter Your Present Address Group Group   Step3 Field   DateofBirth Enter Your Date of Birth Group Group   Step4 Field   ContactNo Enter Your Contact no. They should be indented as shown in the following screenshot: Select Group and Step1 and set the Enable property with a value Step1Visible. Select Group and Step2 and set the Enable property with a value Step2Visible. Select Group and Step3 and set the Enable property with a value Step3Visible. Select Group and Step4 and set the Enable property with a value Step4Visible. Then navigate to View | Page Actions (Ctrl+ Alt+ F4) to add actions on the page. In Action Designer, add the following variables: Type Name Caption Action Action1 &Back Action Action2 &Next Action Action3 &Finish Set the following properties for Action1: Property Value Enabled BackEnable Image PreviousRecord InFooterBar Yes Set the following properties for Action2: Property Value Enabled NextEnable Image NextRecord InFooterBar Yes Set the following properties for Action3: Property Value Enabled FinishEnable Image Approve InFooterBar Yes Add this code on the action trigger of Action1: DoStep(CurrentStep-1); CurrPage.UPDATE; Add this code on the action trigger of Action2 and Action3: DoStep(CurrentStep+1); CurrPage.UPDATE; Next, create a new function DoStep. Add the following parameters to the function: Name Type Step Integer Add the following code to the function: CurrentStep:=Step; CASE Step OF 1: BEGIN Step1Visible:=TRUE; Step2Visible:=FALSE; BackEnable := FALSE; NextEnable := TRUE; FinishEnable := FALSE; END; 2: BEGIN Step2Visible:=TRUE; Step1Visible:=FALSE; Step3Visible:=FALSE; BackEnable := TRUE; NextEnable := TRUE; FinishEnable := FALSE; END; 3: BEGIN Step3Visible:=TRUE; Step2Visible:=FALSE; Step4Visible:=FALSE; BackEnable := TRUE; NextEnable := TRUE; FinishEnable := FALSE; END; 4: BEGIN Step4Visible:=TRUE; Step3Visible:=FALSE; BackEnable := TRUE; NextEnable := FALSE; FinishEnable := TRUE; END; 5: BEGIN MESSAGE('%1%2%3%4',FullName,Address, DateofBirth,ContactNo); CurrPage.CLOSE; END END; CurrPage.UPDATE; To start with step 1, add the following code to the OnOpenPage trigger: DoStep(1); Compile, save, and close the page. When you run the page, you will see a window similar to the following screenshot: How it works... The page contains four steps, only one of which is visible at any given time. To control this, we assigned a Boolean variable to all the StepxVisible properties. To control the movement of steps, we need to control our actions. To achieve this, we added other Boolean variables to the Enable property of our actions. Our custom function DoStep decides what should be visible and what should not. It is just a large CASE statement based on the Step variable. In the first frame, for example, we can't move backwards to disable the Back button. We can't finish until we get to the last frame, so the Finish button is disabled until that point. In the Back and Next buttons, we decrement and increment the Step variable, so that the DoStep function knows what to do. To keep track of the current step, we assign a value to the global CurrentStep variable; on the back action, we subtract 1 whereas on the next action we add 1 into CurrentStep. Summary This article provides an overview of how to create different pages using RTC. The pages provide a core way to interact with NAV RTC. Resources for Article : Further resources on this subject: Types of services in Microsoft Dynamics AX 2012 [Article] Overview of Microsoft Dynamics CRM 2011 [Article] Microsoft Office Excel Programming Using VSTO 3.0 [Article]
Read more
  • 0
  • 0
  • 1913

article-image-oracle-goldengate-advanced-administration-tasks-i
Packt
20 Sep 2013
19 min read
Save for later

Oracle GoldenGate- Advanced Administration Tasks - I

Packt
20 Sep 2013
19 min read
(For more resources related to this topic, see here.) Upgrading Oracle GoldenGate binaries In this recipe you will learn how to upgrade GoldenGate binaries. You will also learn about GoldenGate patches and how to apply them. Getting ready For this recipe, we will upgrade the GoldenGate binaries from version 11.2.1.0.1 to 11.2.1.0.3 on the source system, that is prim1-ol6-112 in our case. Both of these binaries are available from the Oracle Edelivery website under the part number V32400-01 and V34339-01 respectively. 11.2.1.0.1 binaries are installed under /u01/app/ggate/112101. How to do it... The steps to upgrade the Oracle GoldenGate binaries are: Make a new directory for 11.2.1.0.3 binaries: mkdir /u01/app/ggate/112103 Copy the binaries ZIP file to the server in the new directory. Unzip the binaries file: [ggate@prim1-ol6-112 112103]$ cd /u01/app/ggate/112103 [ggate@prim1-ol6-112 112103]$ unzip V34339-01.zip Archive: V34339-01.zip inflating: fbo_ggs_Linux_x64_ora11g_64bit.tar inflating: Oracle_GoldenGate_11.2.1.0.3_README.doc inflating: Oracle GoldenGate_11.2.1.0.3_README.txt inflating: OGG_WinUnix_Rel_Notes_11.2.1.0.3.pdf Install the new binaries in /u01/app/ggate/112103: [ggate@prim1-ol6-112 112103]$ tar -pxvf fbo_ggs_Linux_x64_ora11g_64bit.tar Stop the processes in the existing installation: [ggate@prim1-ol6-112 112103]$ cd /u01/app/ggate/112101 [ggate@prim1-ol6-112 112101]$ ./ggsci Oracle GoldenGate Command Interpreter for Oracle Version 11.2.1.0.1 OGGCORE_11.2.1.0.1_PLATFORMS_120423.0230_FBO Linux, x64, 64bit (optimized), Oracle 11g on Apr 23 2012 08:32:14 Copyright (C) 1995, 2012, Oracle and/or its affiliates. All rights reserved. GGSCI (prim1-ol6-112.localdomain) 1> stop * Sending STOP request to EXTRACT EGGTEST1 ... Request processed. Sending STOP request to EXTRACT PGGTEST1 ... Request processed. Stop the manager process: GGSCI (prim1-ol6-112.localdomain) 2> STOP MGRManager process is required by other GGS processes.Are you sure you want to stop it (y/n)? ySending STOP request to MANAGER ...Request processed.Manager stopped. Copy the subdirectories to the new binaries: [ggate@prim1-ol6-112 112101]$ cp -R dirprm /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirrpt /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirchk /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R BR /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirpcs /u01/app/ggate/112103/ [ggate@prim1-ol6-112 112101]$ cp -R dirdef /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirout /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirdat /u01/app/ggate/112103/[ggate@prim1-ol6-112 112101]$ cp -R dirtmp /u01/app/ggate/112103/ Modify any parameter files under dirprm if you have hardcoded old binaries path in them. Edit the ggate user profile and update the value of the GoldenGate binaries home: vi .profile export GG_HOME=/u01/app/ggate/112103 Start the manager process from the new binaries: [ggate@prim1-ol6-112 ~]$ cd /u01/app/ggate/112103/ [ggate@prim1-ol6-112 112103]$ ./ggsci Oracle GoldenGate Command Interpreter for Oracle Version 11.2.1.0.3 14400833 OGGCORE_11.2.1.0.3_PLATFORMS_120823.1258_FBO Linux, x64, 64bit (optimized), Oracle 11g on Aug 23 2012 20:20:21 Copyright (C) 1995, 2012, Oracle and/or its affiliates. All rights reserved. GGSCI (prim1-ol6-112.localdomain) 1> START MGR Manager started. Start the processes: GGSCI (prim1-ol6-112.localdomain) 18> START EXTRACT * Sending START request to MANAGER ... EXTRACT EGGTEST1 starting Sending START request to MANAGER ... EXTRACT PGGTEST1 starting How it works... The method to upgrade the GoldenGate binaries is quite straightforward. As seen in the preceding section, you need to download and install the binaries on the server in a new directory. After this, you would stop the all GoldenGate processes that are running from the existing binaries. Then you would copy all the important GoldenGate directories with parameter files, trail files, report files, checkpoint files, and recovery files to the new binaries. If your trail files are kept on a separate filesystem which is linked to the dirdat directory using a softlink, then you would just need to create a new softlink under the new GoldenGate binaries home. Once all the files are copied, you would need to modify the parameter files if you have the path of the existing binaries hardcoded in them. The same would also need to be done in the OS profile of the ggate user. After this, you just start the manager process and rest of the processes from the new home. GoldenGate patches are all delivered as full binaries sets. This makes the procedure to patch the binaries exactly the same as performing major release upgrades. Table structure changes in GoldenGate environments with similar table definitions Almost all of the applications systems in IT undergo some change over a period of time. This change might include a fix of an identified bug, an enhancement or some configuration change required due to change in any other part of the system. The data that you would replicate using GoldenGate will most likely be part of some application schema. These schemas, just like the application software, sometimes require some changes which are driven by the application vendor. If you are replicating DDL along with DML in your environment then these schema changes will most likely be replicated by GoldenGate itself. However, if you are only replicating only DML and there are any DDL changes in the schema particularly around the tables that you are replicating, then these will affect the replication and might even break it. In this recipe, you will learn how to update the GoldenGate configuration to accommodate the schema changes that are done to the source system. This recipe assumes that the definitions of the tables that are replicated are similar in both the source and target databases. Getting ready For this recipe we are making the following assumptions: GoldenGate is set up to replicate only DML changes between the source and target environments. The application will be stopped for making schema changes in the source environment. The table structures in the source and target database are similar. The replication is configured for all objects owned by a SCOTT user using a SCOTT.* clause. The GoldenGate Admin user has been granted SELECT ANY TABLE in the source database and INSERT ANY TABLE, DELETE ANY TABLE, UPDATE ANY TABLE, SELECT ANY TABLE in the target database. The schema changes performed in this recipe are as follows: Add a new column called DOB (DATE) to the EMP table. Modify the DNAME column in the DEPT table to VARCHAR(20). Add a new table called ITEMS to the SCOTT schema: ITEMS ITEMNO NUMBER(5) PRIMARY KEY NAME VARCHAR(20) Add a new table called SALES to the SCOTT schema: SALES INVOICENO NUMBER(9) PRIMARY KEY ITEMNO NUMBER(5) FOREIGN KEY ITEMS(ITEMNO) EMPNO NUMBER(4) FOREIGN KEY EMP(EMPNO) Load the values for the DOB column in the EMP table. Load a few records in the ITEMS table. How to do it… Here are the steps that you can follow to implement the preceding schema changes in the source environment: Ensure that the application accessing the source database is stopped. There should not be any process modifying the data in the database. Once you have stopped the application, wait for 2 to 3 minutes so that all pending redo is processed by the GoldenGate extract. Check the latest timestamp read by the Extract and Datapump processes and ensure it is the current timestamp: GGSCI (prim1-ol6-112.localdomain) 9> INFO EXTRACT EGGTEST1 GGSCI (prim1-ol6-112.localdomain) 10> INFO EXTRACT * EXTRACT EGGTEST1 Last Started 2013-03-25 22:24 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:07 ago) Log Read Checkpoint Oracle Redo Logs 2013-03-25 22:35:06 Seqno 350, RBA 11778560 SCN 0.11806849 (11806849) EXTRACT PGGTEST1 Last Started 2013-03-25 22:24 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:04 ago) Log Read Checkpoint File /u01/app/ggate/dirdat/st000010 2013-03-25 22:35:05.000000 RBA 7631 Stop the Extract and Datapump processes in the source environment: GGSCI (prim1-ol6-112.localdomain) 1> STOP EXTRACT * Sending STOP request to EXTRACT EGGTEST1 ... Request processed. Sending STOP request to EXTRACT PGGTEST1 ... Request processed. Check the status of the Replicat process in the target environment and ensure that it has processed the timestamp noted in step 3: GGSCI (stdby1-ol6-112.localdomain) 54> INFO REPLICAT * REPLICAT RGGTEST1 Last Started 2013-03-25 22:25 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:04 ago) Log Read Checkpoint File ./dirdat/rt000061 2013-03-25 22:37:04.950188 RBA 10039 Stop the Replicat process in the target environment: GGSCI (stdby1-ol6-112.localdomain) 48> STOP REPLICAT * Sending STOP request to REPLICAT RGGTEST1 ... Request processed. Apply the schema changes to the source database: SQL> ALTER TABLE SCOTT.EMP ADD DOB DATE; Table altered. SQL> ALTER TABLE SCOTT.DEPT MODIFY DNAME VARCHAR(20); Table altered. SQL> CREATE TABLE SCOTT.ITEMS ( ITEMNO NUMBER(5) PRIMARY KEY, NAME VARCHAR(20)); Table created. SQL> CREATE TABLE SCOTT.SALES ( INVOICENO NUMBER(9) PRIMARY KEY, ITEMNO NUMBER(5) REFERENCES SCOTT.ITEMS(ITEMNO), EMPNO NUMBER(4) REFERENCES SCOTT.EMP(EMPNO)); Table created. SQL> UPDATE SCOTT.EMP SET DOB=TO_DATE('01-01-1980','DD-MM-YYYY'); 14 rows updated. SQL> INSERT INTO SCOTT.ITEMS VALUES (1,'IRON'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (2,'COPPER'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (3,'GOLD'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (4,'SILVER'); 1 row created. SQL> COMMIT; Commit complete. Apply the schema changes to the target database: SQL> ALTER TABLE SCOTT.EMP ADD DOB DATE; Table altered. SQL> ALTER TABLE SCOTT.DEPT MODIFY DNAME VARCHAR(20); Table altered. SQL> CREATE TABLE SCOTT.ITEMS ( ITEMNO NUMBER(5) PRIMARY KEY, NAME VARCHAR(20)); Table created. SQL> CREATE TABLE SCOTT.SALES ( INVOICENO NUMBER(9) PRIMARY KEY, ITEMNO NUMBER(5) REFERENCES SCOTT.ITEMS(ITEMNO), EMPNO NUMBER(4) REFERENCES SCOTT.EMP(EMPNO)); Table created. SQL> UPDATE SCOTT.EMP SET DOB=TO_DATE('01-01-1980','DD-MM-YYYY'); 14 rows updated. SQL> INSERT INTO SCOTT.ITEMS VALUES (1,'IRON'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (2,'COPPER'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (3,'GOLD'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (4,'SILVER'); 1 row created. SQL> COMMIT; Commit complete. Add supplemental logging for the newly added tables: GGSCI (prim1-ol6-112.localdomain) 4> DBLOGIN USERID GGATE_ADMIN@ DBORATEST Password: Successfully logged into database. GGSCI (prim1-ol6-112.localdomain) 5> ADD TRANDATA SCOTT.ITEMS Logging of supplemental redo data enabled for table SCOTT.ITEMS. GGSCI (prim1-ol6-112.localdomain) 6> ADD TRANDATA SCOTT.SALES Logging of supplemental redo data enabled for table SCOTT.SALES. Alter the Extract and Datapump processes to skip the changes generated by the Application Schema Patch: GGSCI (prim1-ol6-112.localdomain) 7> ALTER EXTRACT EGGTEST1 BEGIN NOW EXTRACT altered. GGSCI (prim1-ol6-112.localdomain) 8> ALTER EXTRACT PGGTEST1 BEGIN NOW EXTRACT altered. Start the Extract and Datapump in the source environment: GGSCI (prim1-ol6-112.localdomain) 9> START EXTRACT * Sending START request to MANAGER ... EXTRACT EGGTEST1 starting Sending START request to MANAGER ... EXTRACT PGGTEST1 starting Start the Replicat process in the target environment: GGSCI (stdby1-ol6-112.localdomain) 56> START REPLICAT RGGTEST1 Sending START request to MANAGER ... REPLICAT RGGTEST1 starting How it works... The preceding steps cover a high level procedure that you can follow to modify the structure of the replicated tables in your GoldenGate configuration. Before you start to alter any processes or parameter file, you need to ensure that the applications are stopped and no user sessions in the database are modifying the data in the tables that you are replicating. Once the application is stopped, we check that all the redo data has been processed by GoldenGate processes and then stop. At this point we run the scripts that need to be run to make DDL changes to the database. This step needs to be run on both the source and target database as we will not be replicating these changes using GoldenGate. Once this is done, we alter the GoldenGate processes to start from the current time and start them. There's more... Some of the assumptions made in the earlier procedure might not hold true for all environments. Let's see what needs to be done in such cases where the environment does not satisfy these conditions: Specific tables defined in GoldenGate parameter files Unlike the earlier example, where the tables are defined in the parameter files using a schema qualifier for example SCOTT.*, if you have individual tables defined in the GoldenGateparameterfiles, you would need to modify the GoldenGate parameter files to add these newly created tables to include them in replication. Individual table permissions granted to the GoldenGate Admin user If you have granted table-specific permissions to the GoldenGate Admin user in the source and target environments, you would need to grant them on the newly added tables to allow the GoldenGate user to read their data in the source environment and also to apply the changes to these tables in the target environment. Supplemental logging for modified tables without any keys If you are adding or deleting any columns from the tables in the source database which do not have any primary/unique keys, you would then need to drop the existing supplemental log group and read them. This is because when there are no primary/unique keys in a table, GoldenGate adds all columns to the supplemental log group. This supplemental log group will have to be modified when the structure of the underlying table is modified. Supplemental log groups with all columns for modified tables In some cases, you would need to enable supplemental logging on all columns of the source tables that you are replicating. This is mostly applicable for consolidation replication topologies where all changes are captured and converted into INSERTs in the target environment, which usually is a Data warehouse. In such cases, you need to drop and read the supplemental logging on the tables in which you are adding or removing any columns. Table structure changes in GoldenGate environments with different table definitions In this recipe you will learn how to perform table structure changes in a replication environment where the table structures in the source and target environments are not similar. Getting ready For this recipe we are making the following assumptions: GoldenGate is set up to replicate only DML changes between the source and target environments. The application will be stopped for making schema changes in the source environment. The table structures in the source and target databases are not similar. The GoldenGate Admin user has been granted SELECT ANY TABLE in the source database and INSERT ANY TABLE, DELETE ANY TABLE, UPDATE ANY TABLE, SELECT ANY TABLE in the target database. The definition file was generated for the source schema and is configured in the replicat parameter file. The schema changes performed in this recipe are as follows: Add a new column called DOB (DATE) to the EMP table. Modify the DNAME column in the DEPT table to VARCHAR(20). Add a new table called ITEMS to the SCOTT schema: ITEMS ITEMNO NUMBER(5) PRIMARY KEY NAME VARCHAR(20) Add a new table called SALES to the SCOTT schema: SALES INVOICENO NUMBER(9) PRIMARY KEY ITEMNO NUMBER(5) FOREIGN KEY ITEMS(ITEMNO) EMPNO NUMBER(4) FOREIGN KEY EMP(EMPNO) Load the values for the DOB column in the EMP table. Load a few records in the ITEMS table. How to do it... Here are the steps that you can follow to implement the previous schema changes in the source environment: Ensure that the application accessing the source database is stopped. There should not be any process modifying the data in the database. Once you have stopped the application, wait for 2 to 3 minutes so that all pending redo is processed by the GoldenGate extract. Check the latest timestamp read by the Extract and Datapump process, and ensure it is the current timestamp: GGSCI (prim1-ol6-112.localdomain) 9> INFO EXTRACT EGGTEST1 GGSCI (prim1-ol6-112.localdomain) 10> INFO EXTRACT * EXTRACT EGGTEST1 Last Started 2013-03-28 10:12 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:07 ago) Log Read Checkpoint Oracle Redo Logs 2013-03-28 10:16:06 Seqno 352, RBA 12574320 SCN 0.11973456 (11973456) EXTRACT PGGTEST1 Last Started 2013-03-28 10:12 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:04 ago) Log Read Checkpoint File /u01/app/ggate/dirdat/st000010 2013-03-28 10:15:43.000000 RBA 8450 Stop the Extract and Datapump processes in the source environment: GGSCI (prim1-ol6-112.localdomain) 1> STOP EXTRACT * Sending STOP request to EXTRACT EGGTEST1 ... Request processed. Sending STOP request to EXTRACT PGGTEST1 ... Request processed. Check the status of the Replicat process in the target environment and ensure that it has processed the timestamp noted in step 3: GGSCI (stdby1-ol6-112.localdomain) 54> INFO REPLICAT * REPLICAT RGGTEST1 Last Started 2013-03-28 10:15 Status RUNNING Checkpoint Lag 00:00:00 (updated 00:00:04 ago) Log Read Checkpoint File ./dirdat/rt000062 2013-03-28 10:15:04.950188 RBA 10039 Stop the Replicat process in the target environment: GGSCI (stdby1-ol6-112.localdomain) 48> STOP REPLICAT * Sending STOP request to REPLICAT RGGTEST1 ... Request processed. Apply the schema changes to the source database: SQL> ALTER TABLE SCOTT.EMP ADD DOB DATE; Table altered. SQL> ALTER TABLE SCOTT.DEPT MODIFY DNAME VARCHAR(20); Table altered. SQL> CREATE TABLE SCOTT.ITEMS ( ITEMNO NUMBER(5) PRIMARY KEY, NAME VARCHAR(20)); Table created. SQL> CREATE TABLE SCOTT.SALES ( INVOICENO NUMBER(9) PRIMARY KEY, ITEMNO NUMBER(5) REFERENCES SCOTT.ITEMS(ITEMNO), EMPNO NUMBER(4) REFERENCES SCOTT.EMP(EMPNO)); Table created. SQL> UPDATE SCOTT.EMP SET DOB=TO_DATE('01-01-1980','DD-MM-YYYY'); 14 rows updated. SQL> INSERT INTO SCOTT.ITEMS VALUES (1,'IRON'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (2,'COPPER'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (3,'GOLD'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (4,'SILVER'); 1 row created. SQL> COMMIT; Commit complete. Apply the schema changes to the target database: SQL> ALTER TABLE SCOTT.EMP ADD DOB DATE; Table altered. SQL> ALTER TABLE SCOTT.DEPT MODIFY DNAME VARCHAR(20); Table altered. SQL> CREATE TABLE SCOTT.ITEMS ( ITEMNO NUMBER(5) PRIMARY KEY, NAME VARCHAR(20)); Table created. SQL> CREATE TABLE SCOTT.SALES ( INVOICENO NUMBER(9) PRIMARY KEY, ITEMNO NUMBER(5) REFERENCES SCOTT.ITEMS(ITEMNO), EMPNO NUMBER(4) REFERENCES SCOTT.EMP(EMPNO)); Table created. SQL> UPDATE SCOTT.EMP SET DOB=TO_DATE('01-01-1980','DD-MM-YYYY'); 14 rows updated. SQL> INSERT INTO SCOTT.ITEMS VALUES (1,'IRON'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (2,'COPPER'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (3,'GOLD'); 1 row created. SQL> INSERT INTO SCOTT.ITEMS VALUES (4,'SILVER'); 1 row created. SQL> COMMIT; Commit complete. Add supplemental logging for the newly added tables: GGSCI (prim1-ol6-112.localdomain) 4> DBLOGIN USERID GGATE_ADMIN@DBORATEST Password: Successfully logged into database. GGSCI (prim1-ol6-112.localdomain) 5> ADD TRANDATA SCOTT.ITEMS Logging of supplemental redo data enabled for table SCOTT.ITEMS. GGSCI (prim1-ol6-112.localdomain) 6> ADD TRANDATA SCOTT.SALES Logging of supplemental redo data enabled for table SCOTT.SALES. Update the parameter file for generating definitions as follows: vi $GG_HOME/dirprm/defs.prm DEFSFILE ./dirdef/defs.def USERID ggate_admin@dboratest, PASSWORD XXXX TABLE SCOTT.EMP; TABLE SCOTT.DEPT; TABLE SCOTT.BONUS; TABLE SCOTT.DUMMY; TABLE SCOTT.SALGRADE; TABLE SCOTT.ITEMS; TABLE SCOTT.SALES; Generate the definitions in the source environment: ./defgen paramfile ./dirprm/defs.prm Push the definitions file to the target server using scp: scp ./dirdef/defs.def stdby1-ol6-112:/u01/app/ggate/dirdef/ Edit the Extract and Datapump process parameter to include the newly created tables if you have specified individual table names in them. Alter the Extract and Datapump processes to skip the changes generated by the Application Schema Patch: GGSCI (prim1-ol6-112.localdomain) 7> ALTER EXTRACT EGGTEST1 BEGIN NOW EXTRACT altered. GGSCI (prim1-ol6-112.localdomain) 8> ALTER EXTRACT PGGTEST1 BEGIN NOW EXTRACT altered. Start the Extract and Datapump in the source environment: GGSCI (prim1-ol6-112.localdomain) 9> START EXTRACT * Sending START request to MANAGER ... EXTRACT EGGTEST1 starting Sending START request to MANAGER ... EXTRACT PGGTEST1 starting Edit the Replicat process parameter file to include the tables: ./ggsci EDIT PARAMS RGGTEST1 REPLICAT RGGTEST1 USERID GGATE_ADMIN@TGORTEST, PASSWORD GGATE_ADMIN DISCARDFILE /u01/app/ggate/dirrpt/RGGTEST1.dsc,append,MEGABYTES 500 SOURCEDEFS ./dirdef/defs.def MAP SCOTT.BONUS, TARGET SCOTT.BONUS; MAP SCOTT.SALGRADE, TARGET SCOTT.SALGRADE; MAP SCOTT.DEPT, TARGET SCOTT.DEPT; MAP SCOTT.DUMMY, TARGET SCOTT.DUMMY; MAP SCOTT.EMP, TARGET SCOTT.EMP; MAP SCOTT.EMP,TARGET SCOTT.EMP_DIFFCOL_ORDER; MAP SCOTT.EMP, TARGET SCOTT.EMP_EXTRACOL, COLMAP(USEDEFAULTS, LAST_UPDATE_TIME = @DATENOW ()); MAP SCOTT.SALES, TARGET SCOTT.SALES; MAP SCOTT.ITEMS, TARGET SCOTT.ITEMS; Start the Replicat process in the target environment: GGSCI (stdby1-ol6-112.localdomain) 56> START REPLICAT RGGTEST1 Sending START request to MANAGER ... REPLICAT RGGTEST1 starting How it works... You can follow the previously mentioned procedure to apply any DDL changes to the tables in the source database. This procedure is valid for environments where existing table structures between the source and the target databases are not similar. The key things to note in this method are: The changes should only be made when all the changes extracted by GoldenGate are applied to the target database, and the replication processes are stopped. Once the DDL changes have been performed in the source database, the definitions file needs to be regenerated. The changes that you are making to the table structures needs to be performed on both sides. There's more… Some of the assumptions made in the earlier procedure might not hold true for all environments. Let's see what needs to be done in cases where the environment does not satisfy these conditions: Individual table permissions granted to the GoldenGate Admin user If you have granted table-specific permissions to the GoldenGate Admin user in the source and target environments, you would need to grant them on the newly added tables to allow the GoldenGate user to read their data in the source environment and also to apply the changes to these tables in the target environment. Supplemental logging for modified tables without any keys If you are adding or deleting any columns from the tables in the source database which do not have any primary/unique keys, you would then need to drop the existing supplemental log group and read them. This is because when there are no primary/unique keys in a table, GoldenGate adds all columns to the supplemental log group. This supplemental log group will need to be modified when the structure of the underlying table is modified. Supplemental log groups with all columns for modified tables In some cases, you would need to enable supplemental logging on all columns of the source tables that you are replicating. This is mostly applicable for consolidation replication topologies where all changes are captured and converted into INSERTs in the target environment, which usually is a Data warehouse. In such cases, you need to drop and read the supplemental logging on the tables in which you are adding or removing any columns.
Read more
  • 0
  • 0
  • 4717

article-image-about-test-studio
Packt
20 Sep 2013
13 min read
Save for later

About Test Studio

Packt
20 Sep 2013
13 min read
(For more resources related to this topic, see here.) Testing concepts The following is a conceptual overview of some fundamental testing terminologies and principles. These are used in day-to-day testing activities. Test case A test case is a scenario that will be executed by the tester or by an automation tool, such as the Test Studio for any of the software testing purposes, such as uncovering potential errors in the system. It contains: Test case identifier: This identifier uniquely distinguishes a test case. Priority: The priority holds a value to indicate the importance of a test case so that the most important ones are executed first and so on. Preconditions: The preconditions describe the initial application state in which the test case is to be executed. It includes actions that need to be completed before starting the execution of the test case, such as performing certain configurations on the application, or other details about the application's state that are found relevant. Procedure: The procedure of a test case is the set of steps that the tester or automated testing tool needs to follow. Expected behavior: It is important to set an expected behavior resulting from the procedure. How else would you verify the functionality you are testing? The expected behavior of a test case is specified before running a test, and it describes a logical and friendly response to your input from the system. When you compare the actual response of the system to the preset expected behavior, you determine whether the test case was a success or a failure. Executing a test case When executing a test case, you would add at least one field to your test case description. It is called the actual behavior and it logs the response of the system to the procedure. If the actual behavior deviates from the expected behavior, an incident report is created. This incident report is further analyzed and in case a flaw is identified in the system, a fix is provided to solve the issue. The information that an incident report would include are the details of the test case in addition to the actual behavior that describes the anomalous events. The following example demonstrates the basic fields found in a sample incident report. It describes a transaction carried out at a bank's ATM: Incident report identifier: ATM-398 Preconditions: User account balance is $1000 Procedure: It includes the following steps: User inserts a card. User enters the pin. Attempts to withdraw a sum of $500. Expected behavior: Operation is allowed Actual behavior: Operation is rejected, insufficient funds in account! Procedure results: Fail The exit criteria The following definition appears in the ISTQB (International Software Testing Qualification Board) glossary: "The set of generic and specific conditions, agreed upon with the stakeholders, for permitting a process to be officially completed. The purpose of exit criteria is to prevent a task from being considered completed when there are still outstanding parts of the task, which have not been finished. Exit criteria are used to report against and to plan when to stop testing. [After Gilb and Graham]" The pesticide paradox Software testing is governed by a set of principles out of which we list the pesticide paradox. The following definition appears in the ISTQB glossary: If the same tests are repeated over and over again, eventually the same set of test cases will no longer find any new defects. To overcome this, "pesticide paradox", the test cases need to be regularly reviewed and revised, and new and different tests need to be written to exercise different parts of the software or system to potentially find more defects. Element recognition Element recognition is a pillar of automated test execution as the tool used can't perform an action on an object unless it recognizes it and knows how to find it. Element identification is important in making the automated scripts less fragile during execution. This topic will be reflected in this article. Testing phases The following set of fundamental testing phases is based on their definition by ISTQB. Other organizations might name them differently or include different activities in them. Test planning and control: Test objectives and activities are set during test planning and a test plan is created. It can include: Test strategy: The general approach to testing the application Test tools: Reporting tools, automated testing tool, and so on Test techniques : Will be discussed in the next section Human resources: The personnel needed to carry out the testing As for test control, it should be exercised during all the phases to monitor progress and amend the test plan as needed. Test analysis and design: During this phase, the system specifications are analyzed and test cases, along with their data, are designed. They are also prioritized and the testing environment is identified. Test implementation and execution: When implementing your tests and before executing them, you should set up your environment, generate the detailed test cases, run them, and then log and report the results of your findings. Evaluating the exit criteria and reporting: Evaluating exit criteria is important in order to know when to stop testing. Occasionally, we find that more tests are needed if the risk in one or more application areas hasn't been fully covered. In case it is decided to stop that test implementation and execution, reports are generated and submitted to the implicated persons. Test closure activities: The test closure activities are designed to facilitate reusing of the test data across different versions and products, as well as to promote evaluating and enhancing the testing process. These activities include saving all the test data and testware in a secure repository, evaluating the testing process, and logging suggested amendments. Testing techniques Ranging from easy and straightforward to complex and machine-computed, many testing techniques guide the design and generation of your test cases. In the this section, we will describe the most basic of these techniques based on the ISTQB standards: Equivalence classes: By definition, an equivalence class is a single class of inputs generating an equivalent output. Vice versa, it could be a single class of outputs generated from equivalent inputs. For example, imagine you need to test a simple numeric field which accepts values from 0 to 100. During your testing, you cannot possibly exhaust all the values, hence we would identify one valid equivalence partition and three invalid partitions as follows: For valid partitions: Values between 0 and 100 inclusive For invalid partitions: Values less than zero Values greater than 100 Nonnumeric inputs As a result, you now choose tests from the four equivalence classes instead of testing all the options. The value of equivalence classes analysis lies in the reduction of testing time and effort. Boundary values: When choosing boundary value analysis, you study the limits of your system input. Typically, they are the logical minimum and maximum values in addition to technical or computational limits, such as register sizes, buffer sizes, or memory availability. After determining your logical and technical limits, you would test the system by inputting the actual boundary, the boundary decremented by the smallest possible unit, and the boundary increment by the smallest possible unit. Assuming our system is an application form where you need to enter your first name in one of the fields, you can proceed with a boundary value analysis on the length of the first name string. Considering that the smallest input is one character, and the largest input is one hundred, our boundary values analysis will lead to a test for strings having the following number of characters: zero (empty input), one, two, ninety-nine, one hundred, and one hundred and one. Decision tables: In certain systems, many rules may be interacting with each other to produce the output, such as a security matrix. For instance, let's assume your system is a document management system. The possible factors determining whether a user will have view rights or not are as follows: Belonging to user groups with a permission set for each group Having an individual permission for each user Having access to the documents' file path These factors are called the conditions of the decision table, where the actions might be reading, editing, or deleting a document. A decision table would allow you to test and verify every combination of the listed conditions. Certain rules might simplify your table, but they are outside the scope of this article. The resulting decision table for the previous example of document management system is illustrated as follows: Decision table for user rights State transition diagram: In some systems, not only do the actions performed determine the output and the routing of the application, but also the state in which the system was in before these actions. For such systems, a state transition diagram is used to generate test cases. Firstly, the state transition diagram is drawn with every state as a circle and every possible action as an arrow. Conditions are written between square brackets and the output is preceded by a forward slash. Secondly, each action represented in the diagram is attempted from an initial state. Thirdly, test cases are generated by looping around the state transition diagram and by choosing different possible paths while varying the conditions. The expected behavior in state transition test cases are both the output of the system and the transition to the next expected state. In the following sample diagram, you will find the state transition diagram of a login module: State transition diagram for user authentication to the system About Test Studio This section gives the list of features provided in Test Studio: Functional test automation: The Test Studio solution to functional test automation is going to be discovered through the following topics: building automated tests, using translators and inserting verifications, adding coded steps, executing tests and logging, adding custom logging, inserting manual steps, assigning and reading variables in tests, debugging errors, and integrating automated test creations with Visual Studio. Data-driven architecture: Test Studio offers built-in integration with data sources, allowing you to apply the data-driven architecture during test automation. This feature includes binding tests to SQL, MS Excel, XML, and local data sources, creating data-driven verification, and integrating data-driven architecture with normal automated execution contexts. Element recognition: Element recognition is a powerful feature in Test Studio from which it derives additional test reliability. Element recognition topics will be covered through Test Studio Find expressions for UI elements, element repository consolidation and maintenance, and specialized Find chained expressions. Manual testing: In addition to automated testing, Test Studio guides the manual testing process. Manual testing includes creating manual test steps, integrating with MS Excel, converting manual tests to hybrid, and executing these two types of tests. Organizing the test repository and source control: Tests within the Test Studio project can be organized and reorganized using the features embedded in the tool. Its integration with external source control systems also adds to this management process. The underlying topics are managing tests under folders, setting test properties, and binding your test project to source control from both Test Studio and Visual Studio. Test suites execution and reporting: Grouping tests under test suites is achievable through the Test Studio test lists. This feature comprises creating static and dynamic test lists, executing them, logging their execution result, viewing standard reports, and extending with custom reports. Extended libraries: Extending testing framework automation functionalities for Test Studio is an option available through the creation of Test Studio plugin libraries. Performance testing: In Test Studio, nonfunctional testing is firstly addressed with performance testing. This feature covers developing performance tests, executing them, gathering performance counters, and analyzing and baselining execution results. Load testing: Nonfunctional testing in Test Studio is augmented with another type of test, which is load testing. This topic covers configuring Test Studio load testing services, developing load tests, recording HTTP traffic, creating user profiles and workloads, monitoring machines, gathering performance metrics, executing load tests, and creating custom charts Mobile testing: Test Studio is extended with a version specialized in iOS web, native and hybrid apps testing. It includes preparing applications for testing within Test Studio, creating automated tests, inserting verifications on UI elements, registering applications on the web portal, syncing test projects, sending and viewing built-in feedback messages, sending and viewing crash reports, and managing and monitoring registered applications through web portals. Approach While reading this article, you will find a problem-based approach to automating tests with Test Studio. The following general approach might vary slightly between the different examples: General problem: We will start by stating the general problem that you may face in real-life automation Real-life example: We will then give a real-life example based on our previous experience in software testing Solutions using the Test Studio IDE: Having described the problem, a solution using the Test Studio IDE will be provided Solutions using code: Finally, some solutions will be provided by writing code. Setting up your environment You will get a list of files with this article to help you try the examples properly. The following is an explanation on how to set up the environment to practice the automation examples against the applications under test. The File Comparer application To configure this application environment, you need to: Run the FC_DB-Database Scripts.sql files in the SQL Management Studio. Open the settings.xml file from the solution bin and edit the ConnectionString parameter. Reports The data source files for these reports can be found in the ODCs folder. In order to properly display the charts in the workbook: Edit the ConnectionString parameter inside the ODC extension files. Bind the pivot tables inside the excel workbook to these files as follows: The Execution Metrics for Last Run sheet to the FC_DB-L-EMLR. odc file The Execution Metrics over Time sheet to the FC_DB-MOT.odc file The Feature Coverage sheet to the FC_DB-FC.odc file The Test Execution Duration sheet to the FC_DB-TED.odc file Additional files The following are the additional files used in this article : The Test Studio Automated Solutions folder contains the Test Studio automated solution for the examples in the article The TestStudio.Extension folder is a Visual Studio solution and it corresponds to the Test Studio extension library. Other reference sources Refer to Telerik online documentation for: Test Studio standalone and VS plugin editions found at http://www.telerik.com/automated-testing-tools/support/documentation/user-guide/test-execution/test-list-settings.aspx Mobile testing using Test Studio extension for iOS testing found at http:// www.telerik.com/automated-testing-tools/support/documentation/ mobile-testing/testing.aspx Also, for software testing and automation concepts you can refer to: ISTQB-BCS Certified Tester Foundation Level book, Foundations of Software Testing by Dorothy Graham, Erik Van Veenendaal, Isabel Evans, and Rex Black ISTQB glossary of testing terms 2.2 Summary This article explains in brief about Test Studio, its features, and so on. It gives a basic knowledge of what Test Studio is and some of the useful links. Resources for Article : Further resources on this subject: Load Testing Using Visual Studio 2008: Part 1 [Article] Load Testing Using Visual Studio 2008: Part 2 [Article] Ordered and Generic Tests in Visual Studio 2010 [Article]
Read more
  • 0
  • 0
  • 2331

article-image-testing-backbonejs-applications
Packt
20 Sep 2013
7 min read
Save for later

Testing Backbone.js Applications

Packt
20 Sep 2013
7 min read
(For more resources related to this topic, see here.) Testing Backbone applications is no different than testing any other application; you are still going to drive your code from your specs, except that Backbone is already leveraging a lot of functionality for you, for free. So expect to write less code, and consequently less specs. Testing Backbone Views We already have seen some of the advantages of using the View pattern in Testing Frontend Code, and are already creating our interface components in such a manner. So how can a Backbone View be different from what we have done so far? It retains a lot of the patterns that we have discussed as best practices for creating maintainable browser code, but with some syntax sugar and automation to make our life easier. They are the glue code between the HTML and the model, and the Backbone View's main responsibility is to add behavior to the interface, while keeping it in sync with a model or collection. As we will see, Backbone's biggest triumph is how it makes an easy-to-handle DOM event delegation, a task usually done with jQuery. Declaring a new View Very similar to what we have seen so far, declaring a new View is going to be a matter of extending the base Backbone.Viewobject. To demonstrate how it works we need an example. We are going to create a new View and its responsibility is going to be to render a single investment on the screen. We are going to create it in such a way that allows its use by the InvestmentListView component. This is a new component and spec, written in src/InvestmentView.js and spec/InvestmentViewSpec.jsrespectively. In the spec file, we can write something similar to what we have seen previously: describe("InvestmentView", function() { var view; beforeEach(function() { view = new InvestmentView(); }); it("should be a Backbone View", function() { expect(view).toEqual(jasmine.any(Backbone.View)); });}); Which translates into an implementation that extends the base Backbone View component: (function (Backbone) { var InvestmentView = Backbone.View.extend() this.InvestmentView = InvestmentView;})(Backbone); And now we are ready to explore some of the new functionalities provided by Backbone. The el property Like the View pattern a Backbone View also has an attribute containing the reference to its DOM element. The difference here is that Backbone comes with it by default, providing: view.el: The DOM element view.$el: The jQuery object for that element view.$: A scoped jQuery lookup function (the same way we have implemented And if you don't provide an element on the constructor, it creates an element for you automatically. Of course the element it creates is not attached to the document, and is up to the View's user code to attach it. Here is a common pattern you see while using Views: Instantiate it: var view = new InvestmentView(); Call the render function to draw the View's components view.render() Append its element to the page document: $('body').append(view.el); Given our clean implementation of the InvestmentView, if you would go ahead and execute the preceding code on a clean page, you would get the following result: <body> <div></div></body> An empty div element; that is the default element created by Backbone. But we can change that with a few configuration parameters on the InvestmentView declaration. Let's say we want the DOM element of InvestmentViewto be a list item (li) with an investment CSS class. We could write this spec using the familiar Jasmine jQuery matchers:   describe("InvestmentView", function() { var view; beforeEach(function() { view = new InvestmentView(); }); it("should be a list item with 'investment' class", function() { expect(view.$el).toBe('li.investment'); });}); You can see that we didn't use the setFixtures function, since we can run this test against the element instance available on the View. Now to the implementation; all we have to do, is define two simple attributes in the View definition, and Backbone will use them to create the View's element: var InvestmentView = Backbone.View.extend({ className: 'investment', tagName: 'li'}); By looking at the implementation you might be wondering if we shouldn't test it like we did with in the Backbone Model: Sync and AJAX requests section. Here I would recommend against it, since you wouldn't get any benefit from that approach, as this spec is much more solid. That is great, but how do we add content to that DOM element? That is up to the render function we are going to see next. var view = new InvestmentView({ el: $('body') }); But by letting the View handle its rendering, we get better componentization and we can also gain on performance. Rendering Now that we understand that it is a good idea to have an empty element available on the View, we must get into the details of how to draw on this empty canvas. Backbone Views already come with an available render function, but it is a dummy implementation, so it is up to you to define how it works. Going back to the InvestmentView example, let's add a new acceptance criterion to describe how it should be rendered. We are going to start by expecting that it renders the return of investment as a percentage value. Here is the spec implementation: describe("InvestmentView", function() { var view, investment; beforeEach(function() { investment = new Investment(); view = new InvestmentView({ model: investment }); }); describe("when rendering", function() { beforeEach(function() { investment.set('roi', 0.1); view.render(); }); it("should render the return of investment", function() { expect(view.$el).toContainHtml('10%'); }); });}); That is a very standard spec with concepts that we have seen before and the implementation is just a matter of defining the render function on the InvestmentViewdeclaration: var InvestmentView = Backbone.View.extend({ className: 'investment', tagName: 'li', render: function () { this.$el.html('<p>'+ formatedRoi.call(this) +'<p>'); return this; }});function formatedRoi () { return (this.model.get('roi') * 100) + '%';} It is using the this.$el property to add some HTML content to the View's element. There are some details that are important for you to notice regarding the render function implementation: We are using the jQuery.html function, so that we can invoke the render function multiple times without duplicating the View's content. The render function returns the View instance once it has completed rendering. This is a common pattern to allow chained calls, such as: $('body').append(new InvestmentView().render().el); Now back to the test. You can see that we weren't testing for the specific HTML snippet, but rather, that just 10 percent text was rendered. You could have done a more thoroughly written spec by checking the exact same HTML at the expectation, but that ends up adding test complexity with little benefit. Summary In this article, you have seen how to use Backbone to do some heavy lifting, allowing you to focus more on your application code. I showed you the power of events, and how they make integration between different components much easier, allowing you to keep your models and Views in sync. Resources for Article: Further resources on this subject: The architecture of JavaScriptMVC [Article] Working with JavaScript in Drupal 6: Part 1 [Article] Syntax Validation in JavaScript Testing [Article]
Read more
  • 0
  • 0
  • 1254
article-image-testing-backbonejs-application
Packt
20 Sep 2013
6 min read
Save for later

Testing Backbone.js Application

Packt
20 Sep 2013
6 min read
(For more resources related to this topic, see here.) Testing Backbone applications is no different than testing any other application; you are still going to drive your code from your specs, except that Backbone is already leveraging a lot of functionality for you, for free. So expect to write less code, and consequently less specs. Testing Backbone Views We already have seen some of the advantages of using the View pattern in Testing Frontend Code, and are already creating our interface components in such a manner. So how can a Backbone View be different from what we have done so far? It retains a lot of the patterns that we have discussed as best practices for creating maintainable browser code, but with some syntax sugar and automation to make our life easier. They are the glue code between the HTML and the model, and the Backbone View's main responsibility is to add behavior to the interface, while keeping it in sync with a model or collection. As we will see, Backbone's biggest triumph is how it makes an easy-to-handle DOM event delegation, a task usually done with jQuery. Declaring a new View Declaring a new View is going to be a matter of extending the base Backbone.View object. To demonstrate how it works we need an example. We are going to create a new View and its responsibility is going to be to render a single investment on the screen. We are going to create it in such a way that allows its use by the InvestmentListView component. This is a new component and spec, written in src/InvestmentView.js and spec/InvestmentViewSpec.js respectively. In the spec file, we can write something similar to this: describe("InvestmentView", function() { var view; beforeEach(function() { view = new InvestmentView(); }); it("should be a Backbone View", function() { expect(view).toEqual(jasmine.any(Backbone.View)); });}); Which translates into an implementation that extends the base Backbone View component: (function (Backbone) { var InvestmentView = Backbone.View.extend() this.InvestmentView = InvestmentView;})(Backbone); And now we are ready to explore some of the new functionalities provided by Backbone. The el property Like the View pattern a Backbone View also has an attribute containing the reference to its DOM element. The difference here is that Backbone comes with it by default, providing: view.el: The DOM element view.$el: The jQuery object for that element view.$: A scoped jQuery lookup function (the same way we have implemented) And if you don't provide an element on the constructor, it creates an element for you automatically. Of course the element it creates is not attached to the document, and is up to the View's user code to attach it. Here is a common pattern you see while using Views: Instantiate it: var view = new InvestmentView(); Call the render function to draw the View's components view.render() Append its element to the page document: $('body').append(view.el); Given our clean implementation of the InvestmentView, if you would go ahead and execute the preceding code on a clean page, you would get the following result: <body> <div></div></body> An empty div element; that is the default element created by Backbone. But we can change that with a few configuration parameters on the InvestmentView declaration. Let's say we want the DOM element of InvestmentView to be a list item (li) with an investment CSS class. We could write this spec using the familiar Jasmine jQuery matchers: describe("InvestmentView", function() { var view; beforeEach(function() { view = new InvestmentView(); }); it("should be a list item with 'investment' class", function() { expect(view.$el).toBe('li.investment'); });}); You can see that we didn't use the setFixtures function, since we can run this test against the element instance available on the View. Now to the implementation; all we have to do, is define two simple attributes in the View definition, and Backbone will use them to create the View's element: var InvestmentView = Backbone.View.extend({ className: 'investment', tagName: 'li'}); By looking at the implementation you might be wondering if we shouldn't test it. Here I would recommend against it, since you wouldn't get any benefit from that approach, as this spec is much more solid. That is great, but how do we add content to that DOM element? That is up to the render function we are going to see next. var view = new InvestmentView({ el: $('body') }); But by letting the View handle its rendering, we get better componentization and we can also gain on performance. Rendering Now that we understand that it is a good idea to have an empty element available on the View, we must get into the details of how to draw on this empty canvas. Backbone Views already come with an available render function, but it is a dummy implementation, so it is up to you to define how it works. Going back to the InvestmentView example, let's add a new acceptance criterion to describe how it should be rendered. We are going to start by expecting that it renders the return of investment as a percentage value. Here is the spec implementation: describe("InvestmentView", function() { var view, investment; beforeEach(function() { investment = new Investment(); view = new InvestmentView({ model: investment }); }); describe("when rendering", function() { beforeEach(function() { investment.set('roi', 0.1); view.render(); }); it("should render the return of investment", function() { expect(view.$el).toContainHtml('10%'); }); });}); That is a very standard spec with concepts that we have seen before and the implementation is just a matter of defining the render function on the InvestmentView declaration: var InvestmentView = Backbone.View.extend({ className: 'investment', tagName: 'li', render: function () { this.$el.html('<p>'+ formatedRoi.call(this) +'<p>'); return this; }});function formatedRoi () { return (this.model.get('roi') * 100) + '%';} It is using the this.$el property to add some HTML content to the View's element. There are some details that are important for you to notice regarding the render function implementation: We are using the jQuery.html function, so that we can invoke the render function multiple times without duplicating the View's content. The render function returns the View instance once it has completed rendering. This is a common pattern to allow chained calls, such as: $('body').append(new InvestmentView().render().el); Now back to the test. You can see that we weren't testing for the specific HTML snippet, but rather, that just 10 percent text was rendered. You could have done a more thoroughly written spec by checking the exact same HTML at the expectation, but that ends up adding test complexity with little benefit. Summary In this article, you have seen how to use Backbone to do some heavy lifting, allowing you to focus more on your application code. I showed you the power of events, and how they make integration between different components much easier, allowing you to keep your models and Views in sync. Resources for Article: Further resources on this subject: The architecture of JavaScriptMVC [Article] Working with JavaScript in Drupal 6: Part 1 [Article] Syntax Validation in JavaScript Testing [Article]
Read more
  • 0
  • 0
  • 2047

article-image-advanced-image-processing-imagej
Packt
20 Sep 2013
9 min read
Save for later

Advanced Image Processing with ImageJ

Packt
20 Sep 2013
9 min read
(For more resources related to this topic, see here.) Selecting regions of your image This section will deal with the process of selecting different regions in your image (lines or whole areas) so that you can perform local measurements using only those selections. Selections, or regions of interest (ROIs), are the basis of region analysis in ImageJ, and open the door to advance measuring of the information in your image, so let's devote some paragraphs to clarify the initial concepts. Let's start by drawing a few lines. Basic selections – lines, length, and profiles Open the tuberculosis.tif test image. It is a multichannel image (one 2D image for Red, another for Green, and the last for Blue) and we will use it because working with selections on images of more than two dimensions offers some extra possibilities. The tool to draw a line is the fifth one from the right on the ImageJ toolbar with a line icon. When you move the mouse over it, the status bar will indicate the kind of things you can do. You will probably think that there are too many things in the description for a single tool, but you can actually use four different tools from the same button. This is always true in ImageJ for tools showing a small red arrow at the bottom right of the tool button. Right-clicking on the tool shows a menu with the similar available tools. Select the straight line tool and draw a line by clicking anywhere on the image and moving the mouse without releasing the mouse button until you want to end your line. While the line is being drawn, the status bar shows relevant information: the current coordinates, the angle of your line with respect to the horizontal and the total length, so you can easily create a line of a specific length. But what if you want to measure your line after you drew it carefully on your image? You only need to navigate to Analyze | Measure ( Ctrl + M). By navigating to Analyze | Set Measurements... You can select which measurements you want to obtain. These are the ones that will be shown on a floating window called Results. Depending on the particular selections done on your ImageJ installation, the parameters shown on your result window will differ from the ones shown here. A line can also be used to calculate a profile, that is, a plot of the image values along the line. The profile is a simple yet a very useful tool to extract the values along a line that has some meaning in our image. We can use these values to compare the results from different processing algorithms or imaging devices. Draw a straight line on the top-left corner of the tuberculosis.tif image. You should obtain something similar to the following screenshot: Now plot the profile by navigating to Analyze | Plot Profile (Ctrl + K). The resulting profile corresponds to the red channel, the one that was selected on the image with the channel slider at the bottom. Let's check the profile for the different channels by clicking on the Live button at the bottom right part of the profile window. Now every time you modify something that influences the profile plotting, the plot will be updated in real time; this also applies to modifications of the line itself by clicking and dragging on the points placed along its length (the mouse pointer changes to a hand to indicate that you can click and modify the line).   The line we have drawn crosses two round shapes. The profiles show the intensities along this line in every channel. The big red shape represents values near 100 in the Red channel, below 50 in the Green, and almost zero in the Blue. The small green shape has very high values in the three channels because it is very intense, with a wider coverage for the Green channel. There is a simple tool that is also available called Angle tool. As you can imagine, by clicking on three independent points it measures the resulting angle. The value is modified if you move any of the vertices. Results from any measure or profile can be saved in a text file extensions, allowing you to analyze these data with other software such as Microsoft Excel. Drawing regions of interest over an area In the previous section we presented the straight line tool and also indicated that the corresponding button in the toolbar allows selecting another three tools: Segmented Line, Freehand Line, and Arrow Tool. These are a part of a group of tools that ImageJ facilitates in order to draw selections, that are areas of the image that can be used to measure all kinds of parameters (area, length, maximum, perimeter, and so on) or to specify which pixels of the image will be taken into account in further processing steps. We can draw ROIs by combining several tools. The simplest one is the straight line. All these tools are together in the ImageJ toolbar, and are as follows: Rectangle and rounded rectangle tools Oval and elliptical selections, selection brush Polygon Freehand Straight, segmented, and freehand lines Instead of giving a full description of what every tool is and how it is used, we will give you some general guidelines that apply to all of them. After reading them, we will propose you play with them for a while so that you can practice. All tools (except the selection brush) create a shape by clicking with the mouse and moving it without releasing the button until you want to finish. If the tool has options, they can be accessed by double-clicking on the tool icon. The polygon tool creates a side of your polygon every time you click, and closes the shape by double-clicking. When you have created your selection, it can be translated by clicking on it and moving the mouse before releasing the button, provided that the mouse cursor is showing an arrow icon The ROI can be modified by clicking and moving any of the control points, and in that case the mouse icon will change to a small hand When this resizing is done, while holding down a modifier key some restrictions are applied: Shift forces a 1:1 aspect ratio of the selection, Ctrl forces resizing from the center of the selection, and Alt keeps the original aspect ratio. These keys have different effects depending on the kind of selection, and in some cases they won't have any effect. Arrow keys also move the selection, and when combined with Alt, they resize the selection pixel by pixel. Draw different ROIs on any sample image and try all this with different selection tools to understand the possibilities better. When creating selections to be combined with existing ones, use the Shift and Alt keys as modifiers to add and delete newly created selections to existing ones. If you have a selection in your image and want to combine it with the one you are going to create, press Shift while creating it. On the other side, press Alt while creating a selection and it will be removed from the existing one. The result is called a composite selection. Finally, the polygon selection has control points that can be moved independently. If after drawing your polygon you would like to have more control points than the ones you have created, you can click on one control point and press Shift at the same time. The existing control point splits into two, allowing a more detailed modification of the selection. If you prefer to remove some control point just click on it and press the Alt key. An ROI created with the freehand tool won't have control points, but ImageJ offers a way to convert it into a smooth curve with control points by navigating to Edit | Selection | Fit Spline. As a final exercise, try to obtain the following ROIs on the tuberculosis_sample.tif image as follows: Now that you have full control of how to draw different kinds of selections, check how a profile plot can be drawn also from a polyline or a freehand line. The remaining type of tool is the wand tool . This tool is a bit different from the previous ones, as it does not require you to draw the desired contour, but instead generates one based on the pixel values of the region surrounding the initial click. This is called region growing segmentation. When you double-click on the tool icon, a dialog will be shown asking for Mode and the Tolerance. The tolerance is the amount of change that will be permitted in the pixels included in the region, compared to the value of the pixel used as a seed (the one that is being clicked on). The mode selection can be used to impose additional restrictions, such as the need for the pixels to be connected with other pixels already in the region. The following example shows the application of this tool on the tuberculosis_sample.tif image using the Legacy mode and a tolerance of 20.0. You can see that it automatically draws your contour around pixels with values within the range defined by the tolerance: If you want to remove any selections in the image, the easiest way is to select the rectangular region tool and click (but not drag) on any point outside the current selection. When you click on an image with an area selection tool, existing ROIs are deleted. It may sometimes happen that you have accidentally created a very small region and your analysis results are not the ones you are expecting, so this is a very fast way of removing this possible source of errors. Finally, you can also set regions consisting of an individual pixel using a single point (or multipoint) tool . Summary In this article, you have learned how to draw regions of interest over your image, save them for later use, and perform local analysis. Also, the filtering concept has been introduced along with several useful applications. Finally, we have shown how to combine several tools in order to clean an image and perform a particle analysis over it. Resources for Article : Further resources on this subject: Python Image Manipulation [Article] Using Image Processing Techniques [Article] Creating an Image Profile by cloning an existing one [Article]
Read more
  • 0
  • 0
  • 10739

article-image-self-service-business-intelligence-creating-value-data
Packt
20 Sep 2013
15 min read
Save for later

Self-service Business Intelligence, Creating Value from Data

Packt
20 Sep 2013
15 min read
(For more resources related to this topic, see here.) Over the years most businesses have spent considerable amount of time, money, and effort in building databases, reporting systems, and Business Intelligence (BI) systems. IT often thinks that they are providing the necessary information to the business users for them to make the right decisions. However, when I meet the users they tell me a different story. Most often they say that they do not have the information they need to do their job. Or they have to spend a lot of time getting the relevant information. Many users state that they spend more time getting access to the data than understanding the information. This divide between IT and business is very common, it causes a lot of frustration and can cost a lot of money, which is a real issue for companies that needs to be solved for them to be profitable in the future. Research shows that by 2015 companies that build a good information management system will be 20 percent more profitable compared to their peers. You can read the entire research publication from http://download.microsoft.com/download/7/B/8/7B8AC938-2928-4B65-B1B3-0B523DDFCDC7/Big%20Data%20Gartner%20 information_management_in_the_21st%20Century.pdf. So how can an organization avoid the pitfalls in business intelligence systems and create an effective way of working with information? This article will cover the following topics concerning it: Common user requirements related to BI Understanding how these requirements can be solved by Analysis Services An introduction to self-service reporting Identifying common user requirements for a business intelligence system In many cases, companies that struggle with information delivery do not have a dedicated reporting system or data warehouse. Instead the users have access only to the operational reports provided by each line of business application. This is extremely troublesome for the users that want to compare information from different systems. As an example, think of a sales person that wants to have a report that shows the sales pipeline, from the Customer Relationship Management (CRM) system together with the actual sales figures from the Enterprise Resource Planning (ERP) system. Without a common reporting system the users have to combine the information themselves with whatever tools are available to them. Most often this tool is Microsoft Excel. While Microsoft Excel is an application that can be used to effectively display information to the users, it is not the best system for data integration. To perform the steps of extracting, transforming, and loading data (ETL), from the source system, the users have to write tedious formulas and macros to clean data, before they can start comparing the numbers and taking actual decisions based on the information. Lack of a dedicated reporting system can also cause trouble with the performance of the Online Transaction Processing (OLTP) system. When I worked in the SQL Server support group at Microsoft, we often had customers contacting us on performance issues that they had due to the users running the heavy reports directly on the production system. To solve this problem, many companies invest in a dedicated reporting system or a data warehouse. The purpose of this system is to contain a database customized for reporting, where the data can be transformed and combined once and for all from all source systems. The data warehouse also serves another purpose and that is to serve as the storage of historic data. Many companies that have invested in a common reporting database or data warehouse still require a person with IT skills to create a report. The main reason for this is that the organizations that have invested in a reporting system have had the expert users define the requirements for the system. Expert users will have totally different requirements than the majority of the users in the organization and an expert tool is often very hard to learn. An expert tool that is too hard for the normal users will put a strain on the IT department that will have to produce all the reports. This will result in the end users waiting for their reports for weeks and even months. One large corporation that I worked with had invested millions of dollars in a reporting solution, but to get a new report the users had to wait between nine and 12 months, before they got the report in their hand. Imagine the frustration and the grief that waiting this long before getting the right information causes the end users. To many users, business intelligence means simple reports with only the ability to filter data in a limited way. While simple reports such as the one in the preceding screenshot can provide valuable information, it does not give the users the possibility to examine the data in detail. The users cannot slice-and-dice the information and they cannot drill down to the details, if the aggregated level that the report shows is insufficient for decision making. If a user would like to have these capabilities, they would need to export the information into a tool that enables them to easily do so. In general, this means that the users bring the information into Excel to be able to pivot the information and add their own measures. This often results in a situation where there are thousands of Excel spreadsheets floating around in the organization, all with their own data, and with different formulas calculating the same measures. When analyzing data, the data itself is the most important thing. But if you cannot understand the values, the data is of no benefit to you. Many users find that it is easier to understand information, if it is presented in a way that they can consume efficiently. This means different things to different users, if you are a CEO, you probably want to consume aggregated information in a dashboard such as the one you can see in the following screenshot: On the other hand, if you are a controller, you want to see the numbers on a very detailed level that would enable you to analyze the information. A controller needs to be able to find the root cause, which in most cases includes analyzing information on a transaction level. A sales representative probably does not want to analyze the information. Instead, he or she would like to have a pre-canned report filtered on customers and time to see what goods the customers have bought in the past, and maybe some suggested products that could be recommended to the customers. Creating a flexible reporting solution What the companies need is a way for the end users to access information in a user-friendly interface, where they can create their own analytical reports. Analytical reporting gives the user the ability to see trends, look at information on an aggregated level, and drill down to the detailed information with a single-click. In most cases this will involve building a data warehouse of some kind, especially if you are going to reuse the information in several reports. The reason for creating a data warehouse is mainly the ability to combine different sources into one infrastructure once. If you build reports that do the integration and cleaning of the data in the reporting layer, then you will end up doing the same tasks of data modification in every report. This is both tedious and could cause unwanted errors as the developer would have to repeat all the integration efforts in all the reports that need to access the data. If you do it in the data warehouse you can create an ETL program that will move the data, and prepare it for the reports once, and all the reports can access this data. A data warehouse is also beneficial from many other angles. With a data warehouse, you have the ability to offload the burden of running the reports from the transactional system, a system that is built mainly for high transaction rates at high speed, and not for providing summarized data in a report to the users. From a report authoring perspective a data warehouse is also easier to work with. Consider the simple static report shown in the first screenshot. This report is built against a data warehouse that has been modeled using dimensional modeling. This means that the query used in the report is very simple compared to getting the information from a transactional system. In this case, the query is a join between six tables containing all the information that is available about dates, products, sales territories, and sales. selectf.SalesOrderNumber,s.EnglishProductSubcategoryName,SUM(f.OrderQuantity) as OrderQuantity,SUM(f.SalesAmount) as SalesAmount,SUM(f.TaxAmt) as TaxAmtfrom FactInternetSales fjoin DimProduct p on f.ProductKey=p.ProductKeyjoin DimProductSubcategory s on p.ProductSubcategoryKey =s.ProductSubcategoryKeyjoin DimProductCategory c on s.ProductCategoryKey =c.ProductCategoryKeyjoin DimDate d on f.OrderDateKey = d.DateKeyjoin DimSalesTerritory t on f.SalesTerritoryKey =t.SalesTerritoryKeywhere c.EnglishProductCategoryName = @ProductCategoryand d.CalendarYear = @Yearand d.EnglishMonthName = @MonthNameand t.SalesTerritoryCountry = @Countrygroup by f.SalesOrderNumber, s.EnglishProductSubcategoryName You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. The preceding query is included for illustrative purposes. As you can see it is very simple to write for someone that is well versed in Transact-SQL. Compare this to getting all the information from the operational system necessary to produce this report, and all the information stored in the six tables. It would be a daunting task. Even though the sample database for AdventureWorks is very simple, we still need to query a lot of tables to get to the information. The following figure shows the necessary tables from the OLTP system you would need to query, to get the information available in the six tables in the data warehouse. Now imagine creating the same query against a real system, it could easily be hundreds of tables involved to extract the data that are stored in a simple data model used for sales reporting. As you can see clearly now, working against a model that has been optimized for reporting is much simpler when creating the reports. Even with a well-structured data warehouse, many users would struggle with writing the select query driving the report shown earlier. The users, in general, do not know SQL. They typically do not understand the database schema since the table and column names usually consists of abbreviations that can be cryptic to the casual user. What if a user would like to change the report, so that it would show data in a matrix with the ability to drill down to lower levels? Then they most probably would need to contact IT. IT would need to rewrite the query and change the entire report layout, causing a delay between the need of the data and the availability. What is needed is a tool that enables the users to work with the business attributes instead of the tables and columns, with simple understandable objects instead of a complex database engine. Fortunately for us SQL Server contains this functionality; it is just for us database professionals to learn how to bring these capabilities to the business. That is what this article is all about, creating a flexible reporting solution allowing the end users to create their own reports. I have assumed that you as the reader have knowledge of databases and are well-versed with your data. What you will learn in this article is, how to use a component of SQL Server 2012 called SQL Server Analysis Services to create a cube or semantic model, exposing data in the simple business attributes allowing the users to use different tools to create their own ad hoc reports. Think of the cube as a PivotTable spreadsheet in Microsoft Excel. From the users perspective, they have full flexibility when analyzing the data. You can drag-and-drop whichever column you want to, into either the rows, columns, or filter boxes. The PivotTable spreadsheet also summarizes the information depending on the different attributes added to the PivotTable spreadsheet. The same capabilities are provided through the semantic model or the cube. When you are using the semantic model the data is not stored locally within the PivotTable spreadsheet, as it is when you are using the normal PivotTable functionality in Microsoft Excel. This means that you are not limited to the number of rows that Microsoft Excel is able to handle. Since the semantic model sits in a layer between the database and the end user reporting tool, you have the ability to rename fields, add calculations, and enhance your data. It also means that whenever new data is available in the database and you have processed your semantic model, then all the reports accessing the model will be updated. The semantic model is available in SQL Server Analysis Services. It has been part of the SQL Server package since Version 7.0 and has had major revisions in the SQL Server 2005, 2008 R2, and 2012 versions. This article will focus on how to create semantic models or cubes through practical step-by-step instructions. Getting user value through self-service reporting SQL Server Analysis Services is an application that allows you to create a semantic model that can be used to analyze very large amounts of data with great speed. The models can either be user created, or created and maintained by IT. If the user wants to create it, they can do so, by using a component in Microsoft Excel 2010 and upwards called PowerPivot. If you run Microsoft Excel 2013, it is included in the installed product, and you just need to enable it. In Microsoft Excel 2010, you have to download it as a separate add-in that you either can find on the Microsoft homepage or on the site called http://www.powerpivot.com. PowerPivot creates and uses a client-side semantic model that runs in the context of the Microsoft Excel process; you can only use Microsoft Excel as a way of analyzing the data. If you just would like to run a user created model, you do not need SQL Server at all, you just need Microsoft Excel. On the other hand, if you would like to maintain user created models centrally then you need, both SQL Server 2012 and SharePoint. Instead, if you would like IT to create and maintain a central semantic model, then IT need to install SQL Server Analysis Services. IT will, in most cases, not use Microsoft Excel to create the semantic models. Instead, IT will use Visual Studio as their tool. Visual Studio is much more suitable for IT compared to Microsoft Excel. Not only will they use it to create and maintain SQL Server Analysis Services semantic models, they will also use it for other database related tasks. It is a tool that can be connected to a source control system allowing several developers to work on the same project. The semantic models that they create from Visual Studio will run on a server that several clients can connect to simultaneously. The benefit of running a server-side model is that they can use the computational power of the server, this means that you can access more data. It also means that you can use a variety of tools to display the information. Both approaches enable users to do their own self-service reporting. In the case where PowerPivot is used they have complete freedom; but they also need the necessary knowledge to extract the data from the source systems and build the model themselves. In the case where IT maintains the semantic model, the users only need the knowledge to connect an end user tool such as Microsoft Excel to query the model. The users are, in this case, limited to the data that is available in the predefined model, but on the other hand, it is much simpler to do their own reporting. This is something that can be seen in the preceding figure that shows Microsoft Excel 2013 connected to a semantic model. SQL Server Analysis Services is available in the Standard edition with limited functionality, and in the BI and Enterprise edition with full functionality. For smaller departmental solutions the Standard edition can be used, but in many cases you will find that you need either the BI or the Enterprise edition of SQL Server. If you would like to create in-memory models, you definitely cannot run the Standard edition of the software since this functionality is not available in the Standard edition of SQL Server. Summary In this article, you learned about the requirements that most organizations have when it comes to an information management platform. You were introduced to SQL Server Analysis Services that provides the capabilities needed to create a self-service platform that can serve as the central place for all the information handling. SQL Server Analysis Services allows users to work with the data in the form of business entities, instead of through accessing a databases schema. It allows users to use easy to learn query tools such as Microsoft Excel to analyze the large amounts of data with subsecond response times. The users can easily create different kinds of reports and dashboards with the semantic model as the data source. Resources for Article : Further resources on this subject: MySQL Linked Server on SQL Server 2008 [Article] Connecting to Microsoft SQL Server Compact 3.5 with Visual Studio [Article] FAQs on Microsoft SQL Server 2008 High Availability [Article]
Read more
  • 0
  • 0
  • 3004
article-image-web-services-and-forms
Packt
19 Sep 2013
6 min read
Save for later

Web Services and Forms

Packt
19 Sep 2013
6 min read
(For more resources related to this topic, see here.) Creating a Dynamics AX web service There are a number of web services that have already been created and deployed with the standard Dynamics AX install. There are a lot more services that you can publish as web services through the AOT in just a matter of minutes, allowing you to access and update almost any area of Dynamics AX from other applications. In this recipe, we will show you how you can create new web services from within the Dynamics AX development environment. How to do it... To create a new web service within Dynamics AX, follow these steps: From within the AOT explorer, create a new project for the web service. From inside the project, right-click on the project name and from the New submenu, select Service Group to create a new web service group. Rename your service group to be something a little more appropriate. In this case, we are creating a sales order web service; so we will rename it as SalesOrderService. From the AOT browser, open up the Services group, find the service that you want to publish as a web service, and then drag it over onto your new project service group. In this recipe, we selected the SalesSalesOrderService , which has all of the logic to create sales orders. You can continue adding as many services into your service group as you like. When you have finished adding services, right-click on the service group that you created and select the Deploy Service Group menu item. This will process the service group and create a web service for you. How it works... To see the web service that was created, open the Inbound ports option from the Services and Application Integration Framework folder of the Setup group in the System administration area page. Your new service should show up there. If you look at the WSDL URI: field for the inbound port, you will find the URL for the web service itself. If you browse to that location, you will see the schema for the web service that you will use for other applications to call, in order to update Dynamics AX. For us it's not that user-friendly, but for applications, this is all they need to know. Creating a web service wrapper The web services that Dynamics AX creates seem to work best for programming interfaces, and sometimes programs have problems with the format of the web service call. InfoPath is one of these programs. So, we need to wrap the Dynamics AX service within a web service wrapper that InfoPath is able to use. This is not as complicated as it sounds though, and you can quickly do this with Visual Studio. In this recipe, we will show how you can create a web service wrapper through Microsoft Visual Studio that we can use from within InfoPath. Getting ready In order to do this you need to have a copy of Visual Studio. We will be using Visual Studio 2010 in our example, but you should be able to create similar web service wrappers using earlier versions as well. How to do it... To create a web service wrapper, follow these steps: From within Visual Studio, create a new web project and from the template library, select the ASP.NET Web Service Application template. This will create your web service shell that will be modified to call the Dynamics AX web service. To link the Dynamics AX web service to our project so that we are able to call it, right-click on the References folder in Solution Explorer and select the Add Service Reference... menu item. From within the Add Service Reference dialog box, paste the URL for your Dynamics AX web service and click on the Go button. This will allow Visual Studio to discover the web service, and you will be able to see all of the operations that are exposed. Change the name in the Namespace: field to match the web service name so that it will be easier to remember in the later steps, and then click on the OK button. When you return to your web service project, you will be able to see the web service reference in the Service References group within Solution Explorer . Within the header of the web service code, add an entry for your service reference as follows: using AXSalesOrderService.SalesOrderServiceReference; Now, replace the HelloWorld web method code that is added to the web service by default with the following code that will use the web service to create a new sales order: [WebMethod] public string NewSalesOrder( string company, string language, string custAccount, string PONumber, string itemID, decimal salesQty, string salesUnit ) { SalesOrderServiceClient client = new SalesOrderServiceClient(); AxdSalesOrder salesOrder = new AxdSalesOrder(); AxdEntity_SalesTable salesTable = new AxdEntity_SalesTable(); AxdEntity_SalesLine salesLine = new AxdEntity_SalesLine(); CallContext callContext = new CallContext(); EntityKey[] keys; EntityKey key; KeyField fld; salesTable.CustAccount = custAccount; salesTable.ReceiptDateRequested = new DateTime(2013, 03, 20); salesLine.ItemId = itemID; salesLine.SalesQty = salesQty; salesLine.SalesUnit = salesUnit; salesTable.SalesLine = new AxdEntity_SalesLine[] { salesLine }; salesTable.PurchOrderFormNum = PONumber; salesTable.SalesType = AxdEnum_SalesType.Sales; salesOrder.SalesTable = new AxdEntity_SalesTable[] { salesTable }; callContext.Company = company; callContext.Language = language; keys = client.create(callContext, salesOrder); key = keys[0]; fld = key.KeyData[0]; return fld.ToString(); } You can see this in the following screenshot: Then, compile your web service. How it works... When you compile your program and run it, you will be taken to the web interface for the new web service showing all of the methods that you've exposed. If you click on the NewSalesOrder web service call, you will be able to see all the parameters that are required to perform the web service. You can test your web service by filling in the parameters and then clicking on Invoke . This will perform the web service and return with the results of the call. With a little bit of extra code, you can have the web service return back the order number as well. To double-check if that everything worked, you can open up Dynamics AX and you should be able to see the new sales order.
Read more
  • 0
  • 0
  • 1344

article-image-directx-graphics-diagnostic
Packt
19 Sep 2013
6 min read
Save for later

DirectX graphics diagnostic

Packt
19 Sep 2013
6 min read
(For more resources related to this topic, see here.) Debugging a captured frame is usually a real challenge in comparison with debugging C++ code. We are dealing with hundreds of thousands of more, pixels that are produced, and in addition, there might be several functions being processed by the GPU. Typically, in modern games, there are different passes on a frame constructing it; also, there are many post-process renderings that will be applied on the final result to increase the quality of the frame. All these processes make it quite difficult to find why a specific pixel is drawn with an unexpected color during debugging! Visual Studio 2012 comes with a series of tools that intend to assist game developers. The new DirectX graphics diagnostics tools are a set of development tools integrated with Microsoft Visual Studio 2012, which can help us to analyze and debug the frames captured from a Direct3D application. Some of the functionalities of these tools come from the PIX for a Windows tool, which is a part of DirectX SDK. Please note that the DirectX graphics diagnostics tools are not supported by Visual Studio 2012 Express at the time of writing this article. In this article, we are going to explain a complete example that shows how to use graphics diagnostics to capture and analyze the graphics information of a frame. Open the final project of this article, DirectX Graphics Diagnostics, and let's see what is going on with the GPU. Intel Graphics Performance Analyzer (Intel GPA) is another suite of graphics analysis and optimization tools that are supported by Windows Store applications. At the time of writing this article, the final release of this suite (Intel GPA 2013 R2) is able to analyze Windows 8 Store applications, but tracing the captured frames is not supported yet. Also, Nvidia Nsight™ Visual Studio Edition 3.1 is another option which supports Visual Studio 2012 and Direct3D 11.1 for debugging, profiling, and tracing heterogeneous compute and graphics application. Capturing the frame To start debugging the application, press Alt + F5 or select the Start Diagnostics command from Debug | Graphics | Start Diagnostics, as shown in the following screenshot: You can capture graphics information by using the application in two ways. The first way is to use Visual Studio to manually capture the frame while it is running, and the second way is to use the programmatic capture API. The latter is useful when the application is about to run on a computer that does not have Visual Studio installed or when you would like to capture the graphics information from the Windows RT devices. For in the first way, when the application starts, press the Print Screen key (Prt Scr). For in the second way, for preparing the application to use the programmatic capture, you need to use the CaptureCurrentFrame API. So, make sure to add the following header to the pch.h file: #include <vsgcapture.h> For Windows Store applications, the location of the temp directory is specific to each user and application, and can be found at C:usersusernameAppDataLocalPackagespackage family nameTempState. Now you can capture your frame by calling the g_pVsgDbg->CaptureCurrentFrame() function. By default, the name of the captured file is default.vsglog. Remember, do not start the graphics diagnostics when using the programmatic capture API, just run or debug your application. The Graphics Experiment window After a frame is captured, it is displayed in Visual Studio as Graphics Experiment.vsglog. Each captured frame will be added to the Frame List and is presented as a thumbnail image at the bottom of the Graphics Experiment tab. This logfile contains all the information needed for debugging and tracing. As you can see in the following screenshot, there are three subwindows: the left one displays the captured frames, the right one, which is named Graphics Events List, demonstrates the list of all DirectX events, and finally, the Graphics Pixel History subwindow in the middle is responsible for displaying the activities of the selected pixel in the running frame: Let's start with the Graphics Pixel History subwindow. As you can see in the preceding screenshot, we selected one of the pixels on the spaceship model. Now let us take a look at the Graphics Pixel History subwindow of that pixel, as shown in the following screenshot: The preceding screenshot shows how this pixel has been modified by each DirectX event; first it is initialized with a specific color, then it is changed to blue by the ClearRenderTargetView function and after this, it is changed to the color of our model by drawing indexed primitives. Open the collapsed DrawIndexed function to see what really happens in the Vertex Shader and Pixel Shader pipelines. The following screenshot shows the information about each of the vertices: The input layout of the vertex buffer is VertexPositionNormalTangentColorTexture. In this article, you can see each vertex's value of the model's triangle. Now, we would like to debug the Pixel Shader of this pixel, so just press the green triangular icon to start debugging. As you can see in the following screenshot, when the debug process is started, Visual Studio will navigate to the source code of the Pixel Shader: Now you can easily debug the Pixel Shader code of the specific pixel in the DrawIndexed stage. You can also right-click on each pixel of the captured frame and select Graphics Object Table to check the Direct3D object's data. Following screenshot shows the Graphics Event List subwindow. Draw calls in this list are typically more important events: The event that is displayed with the icon marks a draw event, the one that is displayed with the icon marks an event that occurs before the captured frame, and the user-defined event marker or the group shown with the icon can be defined inside the application code. In this example, we mark an event (Start rendering the model) before rendering the model and mark another event (The model has been rendered) after the model is rendered. You can create these events by using the ID3DUserDefinedAnnotation:: BeginEvent, ID3DUserDefinedAnnotation:: EndEvent, and ID3DUserDefinedAnnotation:: SetMarker interfaces. Summary In this article, you have learned DirectX graphics diagnostic, how to capture the frame, and the graphics Experiment window. Resources for Article: Further resources on this subject: Getting Started with GameSalad [Article] 2D game development with Monkey [Article] Making Money with Your Game [Article]
Read more
  • 0
  • 0
  • 6014
Modal Close icon
Modal Close icon