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-connecting-web-service-should-know
Packt
26 Sep 2013
8 min read
Save for later

Connecting to a web service (Should know)

Packt
26 Sep 2013
8 min read
(For more resources related to this topic, see here.) Getting ready This recipe is going to log a large JSON message to the console, so large that it will actually overflow STS's default console buffer. To ensure that we don't miss anything, we're going to change STS's configuration to have an unlimited console buffer. Open the Preferences dialog by selecting Window | Preferences from the menu if you are running Windows, or by pressing ?+, if you are using a Mac. Open the Run/Debug item and select the Console item. Uncheck the Limit console output checkbox, and then click on the OK button. How to do it... Let's start by creating our project and updating its dependencies. Launch the New Spring Project wizard by navigating to File | New | Spring Project in the menu. In the dialog box, enter the project name WebServiceProject, expand the Integration folder, and select Spring Integration Project (Standalone) – Simple. Click on the Next button. Allow STS to download the project template if you are prompted to do so. Enter the groupId as com.example, artifactId as web-service-project, and top-level package as com.example.webserviceproject. Click on the Finish button to create the project. Open the Maven pom.xml file. Click on the Dependencies tab, and add the following dependencies: org.springframework.integration : spring-integrationhttp : ${spring.integration.version} org.springframework : spring-test : 3.1.3.RELEASE (Spring Integration 2.2.4.RELEASE depends on this version of Spring, and it's a good idea to be consistent) org.codehaus.jackson : jackson-core-asl : 1.9.12 org.codehaus.jackson : jackson-mapper-asl : 1.9.12 Save the file to update the project's dependencies. Now let's create an integration test. Expand the src/test/java source folder, right-click on the top-level package under it, and select New | JUnit Test Case from the pop-up menu. Name the test WebServiceTest, and click on the Finish button. We're creating a Spring context test, so add the following annotations to the top of the class: @ContextConfiguration(locations = "classpath:META-INF/spring/integration/spring-integration-context.xml")@RunWith(SpringJUnit4ClassRunner.class) Our test is going to send a Spring Integration message down one channel and then wait for a response on another channel. We need to inject the following two channels into our test: @Autowired private MessageChannel weatherRequest;@Autowired private SubscribableChannel weatherResponse; Create the following test case: @Testpublic void shouldRetrieveWeatherDataFromWebService() {weatherResponse.subscribe(new MessageHandler() {@Overridepublic void handleMessage(Message<?> message)throws MessagingException {Map payload = (Map) message.getPayload();Map observations = (Map) payload.get("observations");List data = (List) observations.get("data");Map latestData = (Map) data.get(0);assertNotNull(latestData);assertEquals("Sydney - Observatory Hill",latestData.get("name"));assertNotNull(latestData.get("air_temp"));assertNotNull(latestData.get("local_date_time_full"));}});weatherRequest.send(MessageBuilder.withPayload(new WeatherRequest("N", "94768")).build());} Add all required imports using Quick Fixes. The instantiation of the WeatherRequest object will cause a compilation error because the class does not yet exist. Use a Quick Fix to create the class, taking care to change its source folder to WebServiceProject/src/main/java. Create the class as follows: package com.example.webserviceproject;public class WeatherRequest {private final String stateCode;private final String locationId;public WeatherRequest(String stateCode, String locationId) {this.stateCode = stateCode;this.locationId = locationId;}public String getStateCode() {return stateCode;}public String getLocationId() {return locationId;}} Run the test. It will fail, complaining that no Spring beans could be injected into our test. We have our failing test. Now it's time to create our integration pipeline. Open spring-integration-context.xml (found in the src/main/ resources/META-INF/spring/integration folder). Click on the Namespaces tab. You will find that the int namespace is already checked. Check the int-http namespace as well. Click on the integration-graph tab and maximize the editor to give yourself more space. This template project has already created an integration pipeline for us, but we want to create our own, so select all of the components in the workspace area by dragging a box around them, and then press the Delete key to remove them. Expand the Channels category and drag a channel component into the workspace. Double-click on it to bring up its properties in the Properties view. Change its id to weatherRequest. Remember to close the Properties view after editing the properties of each integration component. Drag another channel component into the workspace, and use the Properties view to set its id to weatherServiceResponse. Drag a publish-subscribe-channel component into the workspace. Give it the id weatherResponse. Drag a logging-channel-adapter component into the workspace. Give it the id logger, set its level to INFO, and its logger-name to com.example. webserviceproject.webserviceresponse. Now expand the http category and drag an outbound-gateway component into the workspace. Set its id property to weatherService, its url property to http://www.bom.gov.au/fwo/ID{stateCode}60901/ ID{stateCode}60901.{locationId}.json, its http-method to GET, and expected-response-type to java.lang.String. Expand the Transformation category and drag a json-to-object-transformer component into the workspace. Set its type property to java.util.HashMap. Now we need to connect everything together. Select the connection tool from the palette and make the following connections: weatherRequest channel to weatherService gateway weatherService gateway to weatherServiceResponse channel weatherServiceResponse channel to json-to-object-transformer json-to-object-transformer to weatherResponse channel Select the mapping/recipient/wire-tap tool from the palette and create a connection from the weatherServiceResponse channel to the logging-channel-adapter channel. Our pipeline should now look like the following figure: Select the integration tab. In the Integration Overview panel, expand all of the beans and then right-click on the int-http:outbound-gateway bean. Select Insert <int-http:uri-variable> element from the pop-up menu. This will create a new sub element and show its properties on the right side of editor. Set its name property to stateCode and its expression to payload.stateCode. Create another uri-variable property, setting its name to locationId, and its expression to payload.locationId. And we're done! Save the file, then re-run the WebServiceTest. If all was configured correctly, the test will take a few seconds to run (it has to contact the web service), and then you should be rewarded with a green bar. Maximize the Console view, and you will find the JSON string returned from the web service. How it works... In this recipe, we used a few different Spring Integration components to make a request to a web service and to transform its response to a Map class so that our test could pick out pieces of data. We also used a wire tap component to log messages to the console. Channels We have seen a couple of different channel implementations in action in this recipe. The weatherRequest and weatherService channels are examples of the default Spring Integration channel, DirectChannel , which is a simple point-to-point channel (that is, there is one sender on one side of the channel and one receiver on the other). By contrast, the weatherRequest channel is a PublishSubscribeChannel , which allows for multiple receivers to register for message events (in our test, we only had the one).Spring Integration provides a number of other channel types designed for different requirements. See the Spring Integration Reference Manual ( http://static.springsource.org/spring-integration/reference/htmlsingle ) for further information. URI variables You would have noticed when setting the URL property of the HTTP outbound gateway that the value included two placeholders, namely {stateCode} and {locationId}. We configured a URL variable for each of these, giving them the values payload.stateCode and payload.locationId respectively. These are simply JavaBean property references. In our case, the payload was a WeatherRequest instance, and we had defined both the stateCode and locationId JavaBean properties on that class. The values of those properties are substituted into the placeholders in the configured URL string to determine the actual URL requested. Wire taps and logging When we connected the weatherServiceResponse channel with logging-channel-adapter, under the hood, STS configured a special type of channel interceptor called a wire tap. A wire tap takes messages passing through a channel, and sends a copy to another channel. This makes them excellent for logging and auditing purposes. When we configured our logging-channel-adapter , we told it to log at the INFO level using the logger name com.example.webserviceproject.webserviceresponse . We could have used any name, of course, but the log4j configuration provided in the project template (the log4j.xml file under src/main/resources ) already had an INFO level logging threshold configured for com.example.webserviceproject loggers, so it was convenient for us to choose the logger name that we did. Summary In this article, we retrieved weather data from the Australian Bureau of Meteorology and also learned about how STS and Spring Integration allow us to interact with web services with very little effort. Resources for Article : Further resources on this subject: Vaadin project with Spring and Handling login with Spring [Article] So, what is Spring for Android? [Article] Migration to Spring Security 3 [Article]
Read more
  • 0
  • 0
  • 1644

article-image-proportional-line-follower-advanced
Packt
26 Sep 2013
6 min read
Save for later

Proportional line follower (Advanced)

Packt
26 Sep 2013
6 min read
(For more resources related to this topic, see here.) Getting ready First, you will need to build an attachment to hold the color sensor onto the robot. Insert an axle that is five modules long into the color sensor. Place bushings onto the axle on either side of the sensor. This is illustrated in the following figure: Attach the two-pin one-axle cross blocks onto the axle outside the bushings. This is illustrated in the following figure: Insert 3-module pins into the cross blocks as shown in the following figure: The pins will attach to the robot just in front of the castor. The bottom of the color sensor should be approximately leveled with the plastic part of the castor holder. If you are on a flat hard surface, your light sensor will be half a centimeter above the ground. If you are on a soft surface, you may need to add a spacer to raise up the sensor. This is illustrated in the following figure: How to do it... We are going to write a proportional line following code similar to the code used for the ultrasonic motion sensor. We will write the following code: This program contains a loop so the robot will track a line for 30 seconds. The base speed of the robot is controlled by a constant value which in this case, is 15. You will need to determine a desired light sensor value for the robot to track on. You can either read the light sensor reading directly on your EV3 brick, or look at the panel on the lower-right hand corner of your screen. You should see all of the motors and sensors that are currently plugged into your brick. In the following screenshot, the current light sensor reading is 16. When tracking a line, you actually want to track on the edge of a line. Our code is designed to track on the right edge of a black line on a white surface. The line doesn't have to be black (or a white surface), but the stronger the contrast the better. One way to determine the desired light sensor value would be to place the light sensor on the edge of the line. Alternatively, you could take two separate readings on the bright surface and the dark surface and take the average value. In the code we discussed, the average value is 40, but you will have to determine the values which work in your own environment. Not only will the surfaces affect the value, but ambient room light can alter this value. The code next finds the difference between the desired value and the sensor reading. This difference is multiplied by a gain factor, which for the optical proportional line follower will probably be between 0 and 1. In this program, I chose a gain of 0.7. The result is added to the base speed of one motor and subtracted from the based speed of the other motor: MotorBPower = Speed - Gain * (LightSensor - DesiredValue) MotorCPower = Speed + Gain * (LightSensor - DesiredValue) After taking the light sensor readings, practice with several numbers to figure out the best speeds and proportionality constants to make your robot follow a line. How it works... This algorithm will make corrections to the path of the robot based on how far off from the line the robot is. It determines this by calculating the difference between the light sensor reading and the value of the light sensor reading on the edge. Each wheel of the robot rotates at a different speed proportional to how far from the line it is. There is a base speed for each wheel and then they will go either slower or faster for a smooth turning. You will find that a large gain value will be needed for sharp turns, but the robot will tend to overcorrect and wobble when it is following a straight line. A smaller gain and higher speed can work effectively when the line is relatively straight or follows a gradual curve. The most important factor to determine is the desired light sensor value. Although your color sensor can detect several colors, we will not be using that feature in this program. The color sensor included in your kit emits red light and we are measuring the reflection of that reflected light. The height of the sensor above the floor is critical, and there is a sweet spot for line tracking at about half a centimetre above the floor. The light comes out of the sensor in a cone. You want the light reflected into the sensor to be as bright as possible, so if your sensor is too high, the reflected intensity will be weaker. Assuming your color sensor is pointing straight down at the floor (as it is in our robot design), then you will see a circular red spot on the floor. Because the distance between the detector and the light emitter is about 5 to 6 mm, the diameter of this circle should be about 11 mm across. If the circle is large, then your color sensor is too high and the intensity will weaken. If the circle is smaller than this, then the sensor will not pick up the emitted light. The color sensor in the LEGO MINDSTORMS EV3 kit is different from the optical sensors included in the earlier LEGO NXT kits. Depending on your application, you might want to pick up some of the older NXT lights and color sensors. The light sensor in the NXT 1.0 kit could not detect color and only measured reflected intensity of a red LED. What is good about this sensor is that it will actually work flush against the surface and saves the need to calibrate changes due to the ambient lighting conditions. The color sensor in the NXT 2.0 kit actually emitted colored lights and contained a general photo detector. However, it did not directly measure color, but measured the reflection of colored light, which it would emit. This actually allowed you to track along different colored lines, but it was also slower. The new EV3 sensor detects colors directly, works quickly, and emits only red light. Summary This article taught us to alter our robot, so it can track a line using an optical sensor. We used a proportional algorithm and adjusted the parameters for optimum tracking. Finally, we also wrote a program allowing the robot to be calibrated without the use of a computer. Resources for Article : Further resources on this subject: Playing with Max 6 Framework [Article] Panda3D Game Development: Scene Effects and Shaders [Article] Our First Project – A Basic Thermometer [Article]
Read more
  • 0
  • 1
  • 11461

article-image-managing-user-logins
Packt
26 Sep 2013
8 min read
Save for later

Managing User Logins

Packt
26 Sep 2013
8 min read
(For more resources related to this topic, see here.) So, who am I? Once logged in to a system, our user will run inside a certain context. This user context defines the rights and privileges that we, as a user, have on the system. The command to obtain current user information, id, also supports SELinux context information. Try it out, and use the -Z switch as follows: $ id -Zunconfined_u:unconfined_r:unconfined_t On SELinux systems with a targeted policy type, chances are very high that all users are logged in as unconfined_u (the first part of the context). On more restricted systems, the user can be user_u (regular restricted users), staff_u (operators), sysadm_u (system administrators), or any other of the SELinux user types. The SELinux user defines the roles that the user can switch to, which themselves define the domains that the user (or his processes) can run in. By default, a fixed number of SELinux users are available on the system, but administrators can create different SELinux users. It is also the administrator’s task to assign Linux logins to SELinux users. The rationale behind unconfined SELinux is able to provide full system confinement: each and every application runs in its own restricted environment from where it cannot break out of. But that requires fine-grained policies that are equally fast developed as the new versions of all the applications that they confine. The following diagram shows this relation between the policies, the domain applicability towards multiple processes and the development effort. As an example, postfix_cleanup_t is shown as a very fine-grained policy domain (which is used for the cleanup process involved in the Postfix mail infrastructure) whereas the unconfined_t domain is shown as the example for a very broad, almost unlimited access domain: Most applications do not have a dedicated policy (although most security-sensitive or popular ones do) and policies do not adapt as fast as the applications themselves. For many servers though, this fine-grained mandatory access is not necessary. All that is needed is to confine the services that are exposed to the network. To support this, SELinux policy developers created the “unconfined” concept, that is, although still governed by SELinux, the domain or user is not really restricted. Not only are those domains very powerful with respect to privilege, the idea is also that these domains do not need to switch to other domains (unless when they need to switch to a confined domain, of course) and that they are not restricted by constraints that are imposed on confined domains (including MLS). An important asset in this unconfined story is the unconfined_t domain for the unconfined_u SELinux user (with the unconfined_r SELinux role). This is exactly the context that we get when logged in to a default Fedora installation or a Gentoo installation that uses the targeted policy store (or mcs /mls with USE=”unconfined”). Next to the user domains, we also have unconfined process domains for daemons and other applications. Some of these run in the unconfined_t domain as well, but most of them run in their own domain even though they are still unconfined. The seinfo tool can tell us which domains are unconfined by asking for those domains that have the selinux_unconfined_type attribute set as follows: # seinfo -aselinux_unconfined_type -x Defining a domain is unconfined or cannot be toggled by administrators, as this is a pure SELinux policy matter. SELinux users and roles Within SELinux systems, the moment a user logs in, the login system checks to which SELinux user his login is mapped. Then, when a SELinux user is found, the system looks up the role and domain that the user should be in. We all are one SELinux user When we logged in to the system and checked our context using id -Z, we noticed that the presented context is the same regardless of the username through which we logged in to the system. SELinux does not care which Linux user we are, as long as it knows which context we are in. When our login process is triggered, a local definition file will be checked to see which SELinux user is mapped to our login. Let us take a look at the existing login mappings using semanage login –l as follows: # semanage login -lLogin Name SELinux User MLS/MCS Range Service__default__ unconfined_u s0-s0:c0.c1023 *root unconfined_u s0-s0:c0.c1023 *system_u system_u s0-s0:c0.c1023 * In the output, two login names are special for SELinux: the __default__ and system_u definitions: __default__: It is a catchall rule. If none of the other rules match, then the users are mapped to the SELinux user identified in the second column (SELinux user). On targeted systems, all users are mapped to the unconfined_u SELinux user because the policies within targeted systems are meant to confine daemons rather than users. On policy stores that do not support unconfined domains, administrators usually map regular logins to restricted SELinux users while administrative logins are mapped to the staff_u or sysadm_u SELinux users. The system_u line is meant for system processes (non-interactively logged in Linux accounts). It should never be assigned to end user logins. The SELinux user is not the only information of a SELinux mapping. In case of an MLS-enabled system, the mapping also contains information about the sensitivity range in which the user is allowed to work (MLS/MCS Range). This way, two users might both be mapped to the user_u restricted SELinux user, but one might only be allowed to access the low sensitivity (s0) whereas another user might also have access to higher sensitivities (for example, s1). Or, in case of MCS, one user might be mapped to a different set of categories different from another user. As an exercise, let us create a new Linux user called myuser and make sure that, when this user is logged in, the context is that of the unprivileged SELinux user_u user. We accomplish this using the semanage login tool as follows: # semanage login -a -s user_u myuser The -s parameter is used to map a login to a SELinux user, whereas sensitivity (and categories) can be handled with the -r parameter. In the next example, we modify the newly created mapping by limiting the user to the sensitivity range s0-s2 and categories c0 to c4: # semanage login -m -r “s0-s2:c0.c4” myuser The changes take effect when a new login occurs so we should force a logout for these users. The following command locks our myuser account, kills all the processes of that user, and unlocks the user again as follows: # passwd -l myuserLocking password for user myuser.passwd: Success# pkill -KILL -u myuser# passwd -u myuserUnlocking password for user myuser.passwd: Success Also, when an existing user is modified, we should also reset the contexts of that users’ home directory (while he is not logged on). To accomplish this, use restorecon using the -F option as follows: # restorecon -RF /home/myuser That is quite easy. Of course, in larger environments, creating mappings this way for individual users is not manageable. In such cases, it might be better to use (primary) group information. Most regular users are part of the user's Linux group, so let us assign those users to the user_u SELinux user. Accounts that are in the admins Linux group are mapped to sysadm_u . To accomplish this, we use the percentage sign to tell the SELinux tools that this mapping is for groups: # semanage login -a -s user_u “%users”# semanage login -a -s sysadm_u “%admins” Now that the group mappings are in place, we can remove the myuser individual mapping we made earlier as follows: # semanage login -d myuser Summary SELinux maps Linux users onto SELinux users and defines the roles that a user is allowed to be in through the SELinux user definitions. We learned how to manage those mappings and the SELinux users with the semanage application and were able to grant the right roles to the right people. We also saw how the same commands are used to grant proper sensitivity to the user and how we can describe these levels in the setrans.conf file. We used the chcat tool to do most of the category-related management activities. Resources for Article : Further resources on this subject: Linux Shell Script: Logging Tasks [Article] Installing VirtualBox on Linux [Article] Installing, Removing, and Upgrading Software [Article]
Read more
  • 0
  • 0
  • 1043

article-image-learning-bukkit-api
Packt
26 Sep 2013
6 min read
Save for later

Learning the Bukkit API

Packt
26 Sep 2013
6 min read
(For more resources related to this topic, see here.) Introduction to APIs API is an acronym for Application Programming Interface. An API helps to control how various software components are used. CraftBukkit includes the Minecraft code in a form that is easier for developers to utilize in creating plugins. CraftBukkit has a lot of code that we do not need to access for creating plugins. It also includes code that we should not use as it could cause the server to become unstable. Bukkit provides us with the classes that we can use to properly modify the game. Basically, Bukkit acts as a bridge between our plugin and the CraftBukkit server. The Bukkit team adds new classes, methods, and so on, to the API as new features develop in Minecraft, but the preexisting code rarely changes. This ensures that our Bukkit plugins will still function correctly months or even years from now. Even though new versions of Minecraft/CraftBukkit are being released. For example, if Minecraft were to change how an entity's health is handled, we would notice no difference. The CraftBukkit jar would account for this change and when our plugin calls the getHealth() method it would function exactly as it had before the update. Another example of how great the Bukkit API is would be the addition of new Minecraft features, such as new items. Let's say that we've created a plugin that gives food an expiration date. To see if an item is food we'd use the isEdible() method. Minecraft continues to create new items. If one of these new items was Pumpkin Bread, CraftBukkit would flag that type of item as edible and would therefore be given an expiration date by our plugin. A year from now, any new food items would still be given expiration dates without us needing to change any of our code. The Bukkit API documentation Documentation of the Bukkit API can be found at jd.bukkit.org. You will see several links regarding the status of the build (Recommended, Beta, or Development) and the form of the documentation (JavaDocs or Doxygen). If you are new to reading documentation of Java code, you may prefer Doxygen. It includes useful features, such as a search bar and collapsible lists and diagrams. If you are already familiar with reading documentation then you may be more comfortable using the JavaDocs. In the following screenshot, both API docs are side by side for comparison. The traditional JavaDocs are on the left and the Doxygen documentation is on the right. The following figure is the inheritance diagram for LivingEntity from the Doxygen site. Take note that on the site you are able to zoom in and click a box to go to that class. I encourage you to browse through each documentation to decide which one you prefer. They are simply displayed differently. When using the Doxygen API docs, you will have to navigate to the bukkit package to see a list of classes and packages. It can be found navigating to the following links within the left column: Bukkit | Classes | Class List | org | bukkit, as shown in the following screenshot: Navigating the Bukkit API Documentation We can look through this documentation to get a general idea of what we are able to modify on a CraftBukkit server. Server-side plugins are different from client-side mods. We are limited with what we are able to modify in the game using server-side plugins. For example, we cannot create a new type of block but we can make lava blocks rain from the sky. We cannot make zombies look and sound like dinosaurs but we can put a zombie on a leash, change its name to Fido and have it not burn in the daylight. For the most part you cannot change the visual aspect of the game, but you can change how it functions. This ensures that everyone who connects to the server with a standard Minecraft client will have the same experience. For some more examples on what we can do, we will view various pages of the API docs. You will notice that the classes are organized into several packages. These packages help group similar classes together. For example, a Cow , a Player, and a Zombie are all types of entities and thus can be found in the org.bukkit.entity package. So if I were to say that the World interface can be found at org.bukkit. World then you will know that the World class can be found within the bukkit package, which is inside the org package. Knowing this will help you find the classes that you are looking for. The search bar near the top right corner of the Doxygen site is another way to quickly find a class. Let's look at the World class and see what it has to offer. The classes are listed in alphabetical order so we will find World near the end of the list within the bukkit package. Once you click on the World class link, all of its methods will be displayed in the main column of the site under the header Public Member Functions as shown in the following screenshot: A World object is an entire world on your server. By default, a Minecraft server has multiple worlds including the main world, nether, and end. CraftBukkit even allows you to add additional worlds. The methods that are listed in the World class apply to the specific world object. For example, the Bukkit.getWorlds() method will give you a list of all the worlds that are on the server; each one is unique. Therefore if you were to call the getName() method on the first world it may return world while calling the same method on the second world may return world_nether. Summary In this article we learnt about what the reader can do by programming plugins. We also learnt the difference between Bukkit and CraftBukkit and how they relate to Minecraft. The term acronym API was also explained. Resources for Article : Further resources on this subject: Coding with Minecraft [Article] Instant Minecraft Designs – Building a Tudor-style house [Article] CryENGINE 3: Breaking Ground with Sandbox [Article]
Read more
  • 0
  • 0
  • 12089

article-image-2-dimensional-image-filtering
Packt
26 Sep 2013
13 min read
Save for later

2-Dimensional Image Filtering

Packt
26 Sep 2013
13 min read
(For more resources related to this topic, see here.) An introduction to image filtering Morphological operations and edge detection are actually types of image filtering, even though we used them in a black box sense, without really looking under the hood. Hopefully, this approach will get you accustomed to the details of image filtering a little faster. First of all, let's give a general definition of image filtering; it can be explained as the process of modifying the values of the pixels using a function that is typically applied on a local neighborhood of the image. In many situations, applying the function on a neighborhood involves a special operation, called convolution, with an operand called kernel. In this sense, you have already applied such a process in the case of erosion or dilation and even in the case of edge detection. The former processes used the strel function to create a kernel, while the latter used a kernel based on your choice of the edge detection method. But let's not get ahead of ourselves. We will try to take things one step at a time, starting by explaining neighborhood processing. Processing neighborhoods of pixels In the previous paragraph, we mentioned that the filtering process typically takes place on a specific neighborhood of pixels. When this neighborhood process is applied for all pixels, it is called sliding neighborhood operation. In it, we slide a rectangular neighborhood window through all possible positions of the image and modify its central pixel using a function of the pixels in the neighborhood. Let's see how this is done, using a numeric example. We'll start with something simple, like a linear filtering process, that is, averaging. Let's suppose that we have a small image, sized 8x8 pixels and we want to modify its pixel values, so that they get assigned with the rounded average of the pixels' values in their 3x3 neighborhoods. This will be easier to explain by using a real numeric example. Let's explain what happens in the step shown in the following image, in which the central pixel of the highlighted 3x3 neighborhood (in the fourth row and sixth column) will be replaced by the average value of all the pixels in the neighborhood (rounded to the nearest integer): Let the image be called I, the result in pixel I(4,6) will be: Substituting the values of the pixels, we can calculate the average value: Hence, the value of the central pixel of the neighborhood will become 121 (the closest integer to 120.89). By repeating the process described previously for all the pixels of the image, we get a result commonly known as mean filtering or average filtering. The final result of the entire process is shown in the following figure: You may be wondering now; the choice of neighborhood, for the example, was very convenient, but what happens when we want to change the value of a pixel on the borders of the image such as let's say pixel I(1,4)? Why was it set to 77 as shown in the image? This is indeed a valid and natural question, and you are very intuitive if you already thought about it. The answer is that the way to tackle this problem when you want your resulting image to be the same size as your original image is to involve only the neighboring pixels that exist in your calculations. However, since in our example, the calculation that has to be performed is averaging the neighborhood pixels, the denominator will still be 9, hence, it will be like we pad the rest of the neighborhood with zeros. Let's demonstrate this example as well: As shown in the previous image, the central pixel value gets evaluated as follows: Of course, since there is no 0th line, the first three operands of the addition are non-existent, hence set to zero: Therefore, the result of the averaging process for the aforementioned neighborhood will be equal to 77 (as shown in the image). This approach is not the only one we have for the image borders. We could assign the maximum possible value (255 for our example) to the non-existent pixels, or assign them the mean value of the rest of the neighborhood, and so on. The choice we make affects the quality of the borders of the image, as we will see in real pictures later on. The basics of convolution The process described previously was performed in overlapping neighborhoods of the image, but no use of a kernel was mentioned. So, what is this all about? And how does the convolution fit in this framework? Well, the truth is that the process described previously is actually describing the essence of convolution, which is passing a kernel over all possible equally sized neighborhoods of the image and using it to modify the value of the central pixel. The only problem in our case is that we did not use a specific kernel in the process described. Or did we? Let's try to find out using MATLAB code to perform two-dimensional convolution. The 3x3 neighborhood we used for the described process can be replaced by a 3x3 kernel, as long as the final result remains the same. The kernel that accomplishes this effect is a 3x3 matrix with all pixels set to 1/9. Convolving this kernel with the original image produces the same result as the aforementioned example. To demonstrate the process, we can use the two-dimensional convolution MATLAB function conv2 as follows, to get the result: >> original = [132 101 101 107 115 121 110 92 120 124 122 120 129 123 121 129 134 146 144 134 134 132 134 138 143 147 136 121 121 115 107 107 145 147 138 129 119 113 113 122 162 155 152 149 142 129 118 122 127 122 115 113 117 102 95 94 67 74 78 80 89 89 107 109]; % Create original image >> kernel = ones(3,3)*(1/9); % Create kernel >> conv_result = conv2(original, kernel,'same'); % Perform convolution >> final_result = round(conv_result) % Rounding of result The final result obtained is as follows: final_result = 53 78 75 77 79 80 77 50 84 125 122 123 124 124 122 80 90 135 133 129 125 124 123 82 96 142 138 131 124 121 120 80 100 147 142 134 126 120 116 77 95 140 136 130 124 116 112 74 79 117 115 115 112 110 107 72 43 65 65 66 66 67 66 45 As expected, the result is the same as the one calculated using the analytical process described before. The convolution kernel has done its job. In our process, we used a 8x8 original image and a 3x3 kernel with the values of all pixels as 1/9 (this is what happens when you get a 3x3 matrix with all instances of 1 and multiply it by 1/9, as we did) and finally ordered the conv2 function to produce the result using the padding process described earlier for the borders, hence calculating a result with the same dimensions as the original. But how did it do it? What exactly is convolution? Now it is time to fully understand convolution. But first, you must get acquainted with its mathematical equations. Since learning math is not the purpose of this book, we will try to give you just the basics, so that you get an idea of what this operation is all about, as it is invaluable for image filtering. The ugly mathematical truth Let's start with the mathematical definition of convolution for discrete functions (since in digital image processing all functions are discrete). To form our problem in a signal processing sense, we can define it as passing an input image I, through a Linear Space Invariant (LSI) system, performing convolution with a kernel h (also called a filter), to produce an output image, g. Hence, we get the following block diagram: This process is described mathematically by the following equation: where * is the symbol for convolution and the large Σ denotes a sum. The reason we have two sums is because our process is two-dimensional. Without going into too much detail, we can summarize the process described previously using the following steps, which are also followed in the implementation of conv2: Rotate the convolution kernel by 180 degrees to abide by the process in the double sum of the equation. Determine the central pixel of the neighborhood. This is straightforward when the neighborhood has an odd number of rows and columns, but must be based on some rule if either of the dimensions is even. Apply the rotated kernel to each pixel of the input image. This is a multiplication of each pixel in the rotated kernel by the corresponding pixel on the image neighborhood processed. It can be thought of as the weighted sum of the neighborhood pixels. The result of conv2 can be either of the following choices: full: Larger than the original image, taking into account all the pixels that can be computed using the convolution kernel, even if their center falls out of the image. This is the default choice for the function. same: Same size as the original image, using zeros to calculate border pixel values. valid: Smaller than the original image, so that it uses only pixels that have full valid neighbors in the computations. This means that when you want to produce a convolution result with the same size as the original image, you will have to use same as an input, as we did in our previous example. By now, those of you that are not very much into math may be tempted to stop reading. So, let's stop the mathematical jargon and dive into the practical examples. We know what a convolution does and we have seen an example on the pixels of a very small image, using an averaging convolution kernel. So, what does this process really do to an image? Time for action – applying averaging filters in images We will start off with an easy-to-follow example, so that all the theory described previously is demonstrated. In this example, we will also introduce some new MATLAB functions, to facilitate your understanding. Let's start: First, we load our image, which is holiday_image2.bmp: >> img = imread('holiday_image2.bmp'); Then, we generate our convolution kernel, using function fspecial and then rotate it 180 degrees: >> kernel = fspecial('average',3); >> kernel = rot90(kernel,2) The output of the code will be as follows: kernel = 0.1111 0.1111 0.1111 0.1111 0.1111 0.1111 0.1111 0.1111 0.1111 Now, it is time to use the three different ways of convolving our image: >> con1 = conv2(img,kernel); % Default usage ('full') >> con2 = conv2(img,kernel,'same'); % convolution using 'same' >> con3 = conv2(img,kernel,'valid'); % convolution using 'valid' In the previous step, you probably got a warning saying: Warning: CONV2 on values of class UINT8 is obsolete. Use CONV2(DOUBLE(A),DOUBLE(B)) or CONV2(SINGLE(A),SINGLE(B)) instead. This actually means that UNIT8 type will not be supported by conv2 in the future. To be on the safe side, you might want to use the suggestion by MATLAB and convert your image to single prior to convolving it: >> img = single(img); >> kernel = fspecial('average',3); % Create 3x3 averaging kernel >> con1 = conv2(img,kernel); % Default usage ('full') >> con2 = conv2(img,kernel,'same'); % convolution using 'same' >> con3 = conv2(img,kernel,'valid'); % convolution using 'valid' Now, we can show our results in one figure, along with the original image. This time, we are going to use an empty matrix as the second argument in imshow, to avoid having to convert our results to UNIT8: >> figure;subplot(2,2,1),imshow(img,[]),title('Original') >> subplot(2,2,2),imshow(con1,[]),title('full') >> subplot(2,2,3),imshow(con2,[]),title('same') >> subplot(2,2,4),imshow(con3,[]),title('valid') It is obvious that the three results are identical, but there is a small detail. Their size is not. So let's see if we got what we expected. In the Workspace window, you can see the difference in sizes: Let's now discuss the physical, qualitative meaning of averaging an image. What does it exactly do? The answer is; it performs blurring of the image. To examine this effect, we can crop the tower from our original and averaged image and display the result. The tower can be cropped using the following coordinates: >> tower_original = img(51:210,321:440); >> tower_blurred = con2(51:210,321:440); figure >> subplot(1,2,1),imshow(tower_original),title('Original tower') >> subplot(1,2,2),imshow(tower_blurred),title('Blurred tower') The original image and the blurred image are as follows: What just happened? The process described in the previous example demonstrated the usage of convolution in its various implementations, using the averaging kernel produced using fspecial. This function is designed to generate kernels for popular filtering tasks, as we will further analyze in the following sections. In our case, we created a 3x3 kernel of values equal to 1/9 (which is almost equal to 0.1111, hence the result in step 2). Then, the three different choices of convolution were applied and the results were displayed along with the original image. Of course, a detail such as the size of the borders cannot be easily observed in full scale, so we observed the difference in the sizes of the results. Finally, we displayed a part of the original image next to the same part of the same convolution result, to prove that the result of the averaging process is a blurring of the image. Alternatives to convolution Convolution is not the only way to perform image filtering. There is also correlation, which gives us the same result. Filtering an image using correlation can be accomplished by using the MATLAB function called filter2, which performs, as its name implies, a two-dimensional filtering of two images. The first input in this case is a kernel (filter) and the second input is an image (or in a more general case a two-dimensional matrix). We will not go into detail here, just point out that one main difference between the two methods is that correlation does not need the kernel to be rotated. The border issue remains, having the same three approaches as in the case of convolution using conv2. A demonstration on the equivalence of the two functions is given if we type in the following commands: >> img = imread('holiday_image2.bmp'); >> img = img(51:210,321:440); >> kernel = fspecial('average',3); >> kernel180 = rot90(kernel,3); >> conv_result = conv2(img,kernel180,'same'); >> corr_result = filter2(kernel,img,'same'); >> subplot(1,3,1),imshow(img),title('Original') >> subplot(1,3,2),imshow(uint8(conv_result)),title('Blurred - conv2') >> subplot(1,3,3),imshow(uint8(corr_result)),title('Blurred - filter2') The result of the preceding code is displayed as follows: In our example, the two kernels used for conv2 and filter2 are identical, since the averaging filter used is square (3x3) and all its elements are equal. The generalized process shown will be useful when we have a more complex kernel. Using imfilter The two alternative solutions for performing image filtering presented so far have their origin in general two-dimensional signal processing theory. This means that they should be expanded for three-dimensional signals when we have to deal with colored image filtering. The process is pretty straightforward and involves repeating the process for all three separate colored channels. But why do that, when we have a function that takes care of checking the image before applying the filter and then selecting the correct method? This specialized function is called imfilter and it is designed for handling images, regardless if they are grayscale or color. This function can implement both filtering methods described in previous paragraphs and it can also define the result to be same or full. Its extra functionality comes in the selection of the way it handles boundary values, and the automatic processing of color images. Furthermore, this function performs the needed conversions, in case the image input is integer-valued. Combined with the fspecial function, this will probably be your most valuable tool in MATLAB when it comes to image filtering.
Read more
  • 0
  • 0
  • 7346

article-image-preparing-your-first-jquery-mobile-project
Packt
25 Sep 2013
10 min read
Save for later

Preparing Your First jQuery Mobile Project

Packt
25 Sep 2013
10 min read
(For more resources related to this topic, see here.) Building an HTML page Let's begin with a simple web page that is not mobile optimized. To be clear, we aren't saying it can't be viewed on a mobile device. Not at all! But it may not be usable on a mobile device. It may be hard to read (text too small). It may be too wide. It may use forms that don't work well on a touch screen. We don't know what kinds of problems we will have at all until we start testing. (And we've all tested our websites on mobile devices to see how well they work, right?) Let's have a look at the following code snippet: <h1>Welcome</h1> <p> Welcome to our first mobile web site. It's going to be the bestsite you've ever seen. Once we get some content. And a business plan. But the hard part is done! </p> <p> <i>Copyright Megacorp&copy; 2013</i> </p> </body> </html> As we said, there is nothing too complex, right? Let's take a quick look at this in the browser: Not so bad, right? But let's take a look at the same page in a mobile simulator: Wow, that's pretty tiny. You've probably seen web pages like this before on your mobile device. You can, of course, typically use pinch and zoom or double-click actions to increase the size of the text. But it would be preferable to have the page render immediately in a mobile-friendly view. This is where jQuery Mobile comes in. Getting jQuery Mobile In the preface we talked about how jQuery Mobile is just a set of files. That isn't said to minimize the amount of work done to create those files, or how powerful they are, but to emphasize that using jQuery Mobile means you don't have to install any special tools or server. You can download the files and simply include them in your page. And if that's too much work, you have an even simpler solution. jQuery Mobile's files are hosted on a Content Delivery Network (CDN). This is a resource hosted by them and guaranteed (as much as anything like this can be) to be online and available. Multiple sites are already using these CDN hosted files. That means when your users hit your site they may already have the resources in their cache. For this article, we will be making use of the CDN hosted files, but just for this first example we'll download and extract the files we need. I recommend doing this anyway for those times when you're on an airplane and wanting to whip up a quick mobile site. To grab the files, visit http://jquerymobile.com/download. There are a few options here but you want the ZIP file option. Go ahead and download that ZIP file and extract it. (The ZIP file you downloaded earlier from GitHub has a copy already.) The following screenshot demonstrates what you should see after extracting the files from the ZIP file: Notice the ZIP file contains a CSS and JavaScript file for jQuery Mobile, as well as a minified version of both. You will typically want to use the minified version in your production apps and the regular version while developing. The images folder has five images used by the CSS when generating mobile optimized pages. You will also see demos for the framework as well as theme and structure files. So, to be clear, the entire framework and all the features we will be talking about over the rest of the article will consist of a framework of 6 files. Of course, you also need to include the jQuery library. You can download that separately at www.jquery.com. At the time this article was written, the recommended version was 1.9.1. Customized downloads As a final option for downloading jQuery Mobile, you can also use a customized Download Builder tool at http://jquerymobile.com/download-builder. Currently in Alpha (that is, not certified to be bug-free!), the web-based tool lets you download a jQuery Mobile build minus features your website doesn't need. This creates smaller files which reduces the total amount of time your application needs to display to the end user. Implementing jQuery Mobile Ok, we've got the bits, but how do we use them? Adding jQuery Mobile support to a site requires the following three steps at a minimum: First, add the HTML5 DOCTYPE to the page: <!DOCTYPE html>. This is used to help inform the browser about the type of content it will be dealing with. Add a viewport metatag: <metaname="viewport"content="width=device-width,initial-scale="1">. This helps set better defaults for pages when viewed on a mobile device. Finally, the CSS, JavaScript library, and jQuery itself need to be included into the file. Let's look at a modified version of our previous HTML file that adds all of the above: code 1-2: test2.html <!DOCTYPE html> <html> <head> <title>First Mobile Example</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet"href="jquery.mobile-1.3.2.min.css" /> <script type="text/javascript"src = "http://code.jquery.com/jquery-1.9.1.min.js"></script> <script type="text/javascript"src = "jquery.mobile-1.3.2.min.js"></script> </head> <body> <h1>Welcome</h1> <p> Welcome to our first mobile web site. It's going to be the best siteyou've ever seen. Once we get some content. And a business plan. But the hard part is done! </p> <p> <i>Copyright Megacorp&copy; 2013</i> </p> </body> </html> For the most part, this version is the exact same as Code 1-1, except for the addition of the DOCTYPE, the CSS link, and our two JavaScript libraries. Notice we point to the hosted version of the jQuery library. It's perfectly fine to mix local JavaScript files and remote ones. If you wanted to ensure you could work offline, you can simply download the jQuery library as well. So while nothing changed in the code between the body tags, there is going to be a radically different view now in the browser. The following screenshot shows how the iOS mobile browser renders the page now: Right away, you see a couple of differences. The biggest difference is the relative size of the text. Notice how much bigger it is and easier to read. As we said, the user could have zoomed in on the previous version, but many mobile users aren't aware of this technique. This page loads up immediately in a manner that is much more usable on a mobile device. Working with data attributes As we saw in the previous example, just adding in jQuery Mobile goes a long way to updating our page for mobile support. But there's a lot more involved to really prepare our pages for mobile devices. As we work with jQuery Mobile over the course of the article, we're going to use various data attributes to mark up our pages in a way that jQuery Mobile understands. But what are data attributes? HTML5 introduced the concept of data attributes as a way to add ad-hoc values to the DOM ( Document Object Model). As an example, this is a perfectly valid HTML: <div id="mainDiv" data-ray="moo">Some content</div> In the previous HTML, the data-ray attribute is completely made-up. However, because our attribute begins with data-, it is also completely legal. So what happens when you view this in your browser? Nothing! The point of these data attributes is to integrate with other code, like JavaScript, that does whatever it wants with them. So for example, you could write JavaScript that finds every item in the DOM with the data-ray attribute, and change the background color to whatever was specified in the value. This is where jQuery Mobile comes in, making extensive use of data attributes, both for markup (to create widgets) and behavior (to control what happens when links are clicked). Let's look at one of the main uses of data attributes within jQuery Mobile—defining pages, headers, content, and footers: code 1-3: test3.html <!DOCTYPE html> <html> <head> <title>First Mobile Example</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet"href="jquery.mobile-1.3.2.min.css" /> <script type="text/javascript"src = "http://code.jquery.com/jquery-1.9.1.min.js"></script> <script type="text/javascript"src = "jquery.mobile-1.3.2.min.js"></script> </head> <body> <div data-role="page"> <div data-role="header"><h1>Welcome</h1></div> <div data-role="content"> <p> Welcome to our first mobile web site. It's going to be the bestsite you've ever seen. Once we get some content.And a business plan. But the hard part is done! </p> </div> <div data-role="footer"> <h4>Copyright Megacorp&copy; 2013</h4> </div> </div> </body> </html> Compare the previous code snippet to code 1-2, and you can see that the main difference was the addition of the div blocks. One div block defines the page. Notice it wraps all of the content inside the body tags. Inside the body tag, there are three separate div blocks. One has a role of header, another a role of content, and the final one is marked as footer. All the blocks use data-role, which should give you a clue that we're defining a role for each of the blocks. As we stated previously, these data attributes mean nothing to the browser itself. But let's look what at what jQuery Mobile does when it encounters these tags: Notice right away that both the header and footer now have a black background applied to them. This makes them stand out even more from the rest of the content. Speaking of the content, the page text now has a bit of space between it and the sides. All of this was automatic once the div tags with the recognized data-roles were applied. This is a theme you're going to see repeated again and again as we go through this article. A vast majority of the work you'll be doing will involve the use of data attributes. Summary In this article, we talked a bit about how web pages may not always render well in a mobile browser. We talked about how the simple use of jQuery Mobile can go a long way to improving the mobile experience for a website. Specifically, we discussed how you can download jQuery Mobile and add it to an existing HTML page, what data attributes mean in terms of HTML, and how jQuery Mobile makes use of data attributes to enhance your pages. Resources for Article: Further resources on this subject: jQuery Mobile: Collapsible Blocks and Theming Content [Article] Using different jQuery event listeners for responsive interaction [Article] Creating mobile friendly themes [Article]
Read more
  • 0
  • 0
  • 9883
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-configuring-and-managing-mailbox-server-role
Packt
25 Sep 2013
17 min read
Save for later

Configuring and Managing the Mailbox Server Role

Packt
25 Sep 2013
17 min read
(For more resources related to this topic, see here.) Creating and removing mailbox databases To complete the following steps, you will need to launch the Exchange Management Shell or the Exchange Admin Center. For this example, the Mailbox Server where the new databases are created is configured with an additional disk (E:) that will be used to store the database and its logfiles. Despite earlier examples using multiple disks, we're sticking to a single disk in order to keep things simple. However, if you have stored your logfiles and database files on separate volumes, the same principles apply. How to do it... Creating a new mailbox database To create a new mailbox database called MDB01 on server EX01, execute the following command: New-MailboxDatabase –Name "MDB01" –Server "EX01.exblog.be" –LogFolderPath "E:MDB01Logs" –EdbFilePath "E:MDB01MDB01.edb" Unlike the EAC, which offers you to choose whether or not to immediately mount the database, you will need to manually mount the new database after it is created. Have a look later in this article for more information on how to mount/dismount databases. Exchange 2013 no longer dynamically adjusts the amount of memory that is assigned for each database's cache. How much memory is assigned per database depends on the amount of active and passive databases on the servers and is calculated when the Exchange Information Store service starts. That is also why you will see the following message whenever you add or remove a database or database copy to a server: To restart the Exchange Information Store Service, run the following command from an elevated command prompt or PowerShell instance: Restart-Service MSExchangeIS Restarting the Exchange Information Store service will cause all databases on that server to be dismounted. If that server is not a member of a DAG or it is the sole server that contains a given database copy, that will result in downtime for the user while the service restarts. Alternatively, the same action can be performed through the Exchange Admin Center: Navigate to Servers | databases . Click on the plus-sign ( + ) to launch the new database wizard. Enter a name for the database. Click on browse... and select the Mailbox Server where you want to create the database. Specify the EDB and logfile location. Click on Save . Removing a mailbox database Before you can remove a mailbox database, it must not contain active mailboxes anymore. However, it is possible it still contains disconnected or deleted mailboxes that haven't been purged from the database yet. So before you can remove a database, you need to make sure that all mailboxes have been moved to another database. If you don't, you will get an error as shown in the following screenshot: Before you can remove a mailbox database that has multiple database copies in a Database Availability Group, you need to remove the passive copies first. Only when the active database is the only copy that remains and it's empty, you will be able to permanently remove the database. The following commands will move all mailboxes from database MDB01 to database MDB02, including any system mailboxes that might be hosted in MDB01: Get-Mailbox –Database "MDB01" | New-MoveRequest –TargetDatabase "MDB02" Get-Mailbox –Database "MDB01" -Arbitration | New-MoveRequest –TargetDatabase "MDB02" Once you made sure that the database is empty, you can go ahead and remove the database using the following command: Get-MailboxDatabase MDB01 | Remove-MailboxDatabase Executing the command will remove the database from Exchange, but it will not remove the database files. You will have to manually delete the remaining files from the disk. To remove a mailbox database through the EAC, execute the following steps: Navigate to Servers | databases . Select the database you want to remove and click on the garbage bin icon as shown in the following screenshot: Click on Yes to confirm. How it works... Creating a mailbox database is in fact a pretty straightforward process. It suffices to provide a name, database - and log file path locations and let Exchange take care of the rest for you. When creating a new database, Exchange will first create an object in Active Directory and then create the EDB file along with the log stream and search catalog files in the locations that you specified earlier. During the installation of Exchange 2013, several so-called arbitration mailboxes are created automatically. These mailboxes are used for system-related actions, such as distribution group moderation, federated delegation and system notification. The following arbitration mailboxes are created by default and stored in the first (default) mailbox database: SystemMailbox {GUID} Migration.8f3e7716-2011-43e4-96b1-aba62d229136 FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042 Make absolutely sure that you include these arbitration mailboxes when you are emptying a database before removal. If these mailboxes become unavailable or corrupt, one or more of Exchange's features might stop working. Luckily, Exchange helps you remembering and it won't let you remove a database unless it's considered empty and it's safe to remove it. There's more... When trying to physically remove the files immediately after having removed the mailbox database from Exchange, chances are that you will run into the error shown in the following screenshot: Noderunner.exe is a child process of the Microsoft Exchange Search Host Controller service. In order to release the files from the noderunner.exe process, you can do any of the following: Restart the Mailbox Server. Unless your server is part of a Database Availability Group and other servers have copies of the databases on this server, you will have to plan for a little downtime while the server is rebooting. Restart HostControllerService on the Mailbox Server by executing following command from an elevated PowerShell console: Restart-Service HostControllerService Mounting and dismounting mailbox databases Although as an Exchange administrator, there shouldn't be many occasions on which you have to manually mount or dismount a database, sometimes you might be required to intervene because of an issue. The most common case is probably when a disk on which a database or logfiles are stored runs out of disk space. To protect the database, Exchange will automatically dismount the database. To recover from this situation, the administrator must free-up some space and manually re-mount the database. Therefore it's not only important to know how to perform these actions, but also to understand what's happening when they are executed. Getting ready In order to execute the following steps, you will need to log in to the Exchange Management Shell. How to do it... We will learn mounting and dismounting of database in this section. Mounting a database The following command will issue a mount-request for database MDB01: Mount-Database "MDB01" Dismounting a database: Executing the following command will dismount the database MDB01: Dismount-Database "MDB01" How it works... Before Exchange 2013, every database ran within the same process (store.exe) on the Mailbox Server. The introduction of the new Managed Store in Exchange 2013 changed things quite drastically, but for the better: every database is now running within its own process. This approach has some great advantages, such as whenever a database causes its worker process to hang, only a single database is affected whereas before all databases on the server would have suffered from the hanging process. When taking a closer look at the new Managed Store, we can distinguish three important services: Store Service process Store Worker process Exchange Replication Service The Exchange Replication Service could be seen as a sort of traffic control manager that provides a management interface for Exchange databases as it is responsible for issuing mount and dismount requests to the Store Service. Next to that, the Replication Service also keeps an eye on the state of a mailbox database and will, for instance, initiate a database failover when an issue with a database is reported. For each mount request that is issued, the Exchange Store Service will create a new store worker process for the database being mounted. Amongst other tasks, the store worker process itself is responsible for providing effective access to the database. When a database is mounted successfully, Event 3156 will be posted to the Application event log. Subsequently, the store service will terminate the worker process for a database when a dismount request has been issued. During the dismount process, Exchange will set a flag in the database headers telling that it was cleanly dismounted (also referred to as a "clean shutdown"). If this flag isn't present, the database cannot be re-mounted without being repaired first. When a database is dismounted successfully, an Event 3161 will be posted to the Application event log. There's more... To know if and on what server a database is mounted, execute the following steps. Notice the use of the –Status parameter in the following command: Get-MailboxDatabase –Status | Ft Name,*mount* It is also possible to get a quick overview of the databases' status through the EAC. You can do so by navigating to Servers | databases . Moving database files to another location If you adequately sized your environment, including taking into account additional disk space for future growth, chances are that you'll never have to physically move a database to another location. However, sometimes lack of disk space, change of underlying storage subsystem or simply a change in the design of your environment might require you to move database file to another physical location. Getting ready To execute the following steps, launch the Exchange Management Shell. For more information on how to dismount a database have a look at Mounting/dismounting mailbox databases earlier in this article. How to do it... The following command will move the database files of a database called MDB01 to another location: Move-DatabasePath –Identity "MDB01" –EdbFilePath "E:NewPathMDB01MDB01.edb" –LogFolderPath "E:NewPathMDB01Logs" If you run the command while the database is mounted, the Exchange Management Shell will automatically throw a warning and ask for confirmation to dismount the database: Dismounting a database will cause a temporary outage until the move has completed. After the move has completed, Exchange will automatically re-mount the database. There's more... In some cases, you might prefer Exchange not to automatically move the physical files to their new location. This could be the case when you are using Mount Points in Windows Server. Mount Points can easily be reassigned to another location, without having to actually copy the data, therefore saving quite some time; especially when you are working with large databases. Luckily, you can run the same command as before, only this time adding the –ConfigurationOnly parameter. The command will only update the database object's properties in Active Directory without physically moving the files' location: Move-DatabasePath –Identity "MDB01" –EdbFilePath "E:NewPathMDB01MDB01.edb" –LogFolderPath "E:NewPathMDB01Logs" –ConfigurationOnly If you use the –ConfigurationOnly parameter, make sure that you manually move/relocate the database files before attempting to mount it again. If you are working with Mount Points, now is the time you would change the mount point location. Configuring circular logging Circular logging is the process of truncating logfiles as soon as they have been committed into the database. Normally, logfiles are only truncated after a full back. This allows you to restore a database from an earlier time and replay the transactions up to the latest available one. Normally there's no need to enable circular logging but it can come in handy to quickly free up some disk space; although we would prefer extending disk space for a full log drive over enabling circular logging. Another point of attention is that using circular logging comes at a cost, if you need to restore a database from an earlier point in time you won't be able to recover to the time when the database failed, inevitably leading to data loss. That is also one of the reasons why Microsoft recommends only enabling circular logging when you have at least three additional database copies. Getting ready In order to execute the following steps, launch the Exchange Management Shell. How to do it... To enable circular logging for database MDB01, run the following command: Set-MailboxDatabase "MDB01" –CircularLoggingEnabled $true Similarly, the following command will turn off circular logging: Set-MailboxDatabase "MDB01" –CircularLoggingEnabled $false If you enable or disable circular logging for a single database copy, you will have to remount (dismount/mount) the mailbox database for the change to become effective. Databases that are part of a Database Availability Group and have multiple copies don't have to be remounted. How it works... Every action that a user performs, generates one (or more) database transactions. These transactions aren't immediately written to the database. Instead, as a safety-measure, these transactions get written into a logfile first. Only when transactions are safely written to a logfile, they are recorded in the database. Each logfile is 1MB in size. When a logfile fills up, a new one is automatically generated. Transaction logs play an important role at maintaining the consistency of a database. For example, when the store worker process of one of the databases crashes, that database is not dismounted properly and thus it won't have the clean shutdown flag set. As a result, you won't be able to mount the database until it is brought back into a clean shutdown state. Without going into too much detail, the process involved to bring a database back into a consistent state involves replaying logfiles and recording the (partial) transactions from those logfiles into the database. The transactions in the logfiles could be pretty much anything from a new e-mail that was received to a message's read status that has changed. If a logfile that needs to be replayed against the database isn't available, it essentially means that one or more (partial) transactions cannot be recorded and therefore results in data loss. In large environments, each database can generate hundreds even thousands of logfiles each day and could end up using quite some disk space. Although it's not a recommendation, you can enable circular logging which will flush transaction logs as soon as the transactions have been recorded in the database. If you are running a DAG and your database has multiple copies, transaction logs will be flushed as soon as all database copies have recorded the transactions in the database. In case you have a lagged database copy, the logfile will be flushed from the active and passive database copies as soon as each has recorded the transactions into the database and the logfile has been inspected by the lagged copy. Circular logging allows you to save on disk space that would otherwise be used to store the transaction logs. However, when a disaster strikes and you need to restore a database from backup, you will not be able to recover the latest transactions therefore losing data up to the latest backup. So, if you enable circular logging, make sure that you have multiple database copies running in a Database Availability Group; preferably at least three. The idea behind this is that the risk of losing three copies at once is relatively small. Just keep in mind that it's not impossible. Creating and removing mailboxes Creating mailboxes might be one of the simplest tasks within an Exchange environment. Even though the EAC wizard is relatively self-explanatory, there are some caveats to look out for. Especially the distinction between removing and disabling mailboxes might be confusing at first. Getting ready To execute the following steps, log in to the Exchange Admin Center or launch the Exchange Management Shell. How to do it... In this section we will learn how to create and remove mailboxes. Creating a new user with mailbox The following command will create a new user named Mark Sheffield and create a mailbox for that user: New-Mailbox –UserPrincipalName Mark.Sheffield@exblog.be –Alias MSheffield –Database "MDB01" –Name "Mark Sheffield" –OrganizationalUnit "Users" –Password (Converto-Securestring –Asplaintext "P@ssw0rd" –Force) –Firstname "Mark" –LastName "Sheffield" –DisplayName "Mark Sheffield" –ResetPasswordOnNextLogon $true In the example we just saw, some parameters are required, others aren't. If you aren't sure, you can have a look at the PowerShell help or you could just run New-Mailbox. If you haven't specified all required parameters, PowerShell will automatically query you for them. Creating a new mailbox through the EAC is equally easy, just follow these steps: Navigate to Recipients | Mailboxes . Click on the plus-sign ( + ) to start the new mailbox wizard. Click on New User and fill in the other fields, such as First Name , Last Name , and Display name . Click on more options... to configure advanced options like: In what database the mailbox should be created Whether or not an archive should be created What address book policy should be used Click on Save to create the user. Enabling a mailbox for an existing user The following command will create a mailbox for an existing user named Kirk Jones: Enable-Mailbox –Identity "Exblogkjones" –Database "MDB01" To enable a mailbox for an existing user through the EAC refer the following steps: Navigate to Recipients | Mailboxes . Click on the plus-sign ( + ) to start the new mailbox wizard. Click on Existing user and click on browse... to select the user. Fill in the other fields. Click on more options... to configure advanced options such as: In what database the mailbox should be created Whether or not an archive should be created The address book policy Click on Save to create the user. Removing a mailbox This command will effectively remove the mailbox and the user account of user kjones: Remove-Mailbox –Identity kjones To effectively remove the mailbox and the user account through the EAC refer to the following steps: Navigate to Recipients | Mailboxes . Select the user from the list of users. Click the garbage bin icon and select delete . Click Yes to confirm. It's a common error to use Remove-Mailbox to remove a mailbox for a user. Remember that Remove-Mailbox will also remove the user account of that user. If you only want to remove the mailbox (that is, only remove the Exchange-attributes for the user account), run Disable-Mailbox. Disabling a mailbox The following command will disable the mailbox for user kjones, marking the user's mailbox for deletion in the database but without touching the user account itself: Disable-Mailbox –Identity kjones To disable the mailbox for user through the EAC follow these steps: Navigate to Recipients | Mailboxes . Select the user from the list of users. Click the garbage bin icon and select disable . Click Yes to confirm. How it works... Creating and removing mailboxes is a pretty straightforward action. However, the notion of removing and disabling mailboxes can sometimes be confusing. When removing a mailbox, you are not only removing the user's mailbox but also the user account in AD. Disabling a user on the other hand will only mark the user's mailbox for deletion in the database, leaving the user account without a mailbox. Depending on how your databases are configured, the mailbox will remain in the database in a disconnected state until it's past the database's retention time. For example, to raise the deleted mailbox retention period to 60 days, run the following command: Set-MailboxDatabase MDB01 –MailboxRetention 60.00:00:00 There's more... When a mailbox is disabled, it is removed from the list of mailboxes in the EAC and you won't see it anymore when running the Get-Mailbox cmdlet. However, this doesn't necessarily mean the mailbox isn't there anymore. As long as the mailbox is still within the deleted mailbox retention period of your mailbox database, you can re-enable it for the same user or connect it to another user's account, as long as that user doesn't already have a mailbox associated with it. Working with disabled mailboxes Run the following command to see a list of disabled mailboxes for a given database: Get-MailboxStatistics –Database "MDB01" | ? {$_.DisconnectReason –eq "Disabled"} To reconnect the disabled mailbox of Ashley Noel in database DBMBX01 to the user account of Ashley Noel, you can run the following command: Connect-Mailbox "Ashley Noel" –Database "DBMBX01" To connect the disabled mailbox of Ashley Noel to another user, Kirk Jones, run the following command: Connect-Mailbox "Ashley Noel" –Database "DBMBX01" –User "exblogkjones"
Read more
  • 0
  • 0
  • 1589

article-image-implementation-case-study
Packt
25 Sep 2013
21 min read
Save for later

Implementation Case Study

Packt
25 Sep 2013
21 min read
(For more resources related to this topic, see here.) Case study description Weir & Bell Telecom is a manufacturer and retailer of mobile phones and devices that has experienced rapid growth, following a number of highly successful marketing campaigns, and aggressive growth on the high street and internet. It has a very strong line up of products that are considered niche products and that result in high profit margins. With competitors poised to release similar products, the company realizes that, in order to achieve its business objectives and thus maintain its leadership position, it needs to vastly improve and exploit its IT processes and infrastructure. Having grown rapidly, the IT department has not developed in line with the business strategy and the board has recently appointed a new Chief Information Officer (CIO) to oversee the IT department, and to develop an IT strategy that is closely aligned with the business strategy. The aim is to allow the organization to increase the efficiency and responsiveness of its supply chain processes by making effective use of digitized processes. Weir & Bell Telecom has been quite progressive in its IT development to date, and has been using SOA for a number of years. However, SOA has been employed tactically rather than strategically. Furthermore, the company had made some initial investment in Oracle Fusion Middleware products such as Oracle SOA Suite 11g, WebCenter, and Oracle Database. The new CIO has identified SOA as a key enabler to allow the IT department to respond in an agile manner to business and regulatory changes. The assessment The new CIO immediately commissioned a review of the existing SOA infrastructure and an assessment of the maturity of service delivery. The assessment was executed in three primary phases as depicted in the following diagram: In order to gather all the information in a structured way and to subsequently quantify the results in a meaningful fashion, the Oracle Maturity Model was employed. The model was used to quantify each capability domain using a tool created by the company. This allowed the CIO to obtain an accurate view of the "As-Is" situation and to develop and quantify a realistic "To-Be" model. The CIO set aside a period of three weeks (one week per phase) for the execution of the assessment, the elaboration of recommendations and the resulting SOA Roadmap. As the timeframe was very aggressive, it was agreed that the organization should commission the consultancy services of a niche player with a background in SOA and SOA Governance. The phases of the assessment consisted of the following: Evaluate the As-Is: This phase consisted of gathering current information from each capability domain and quantifying it as accurately as possible. The main deliverable of this phase was the assessment model populated with the As-Is data. Evaluate the To-Be: In this phase, a target maturity level was defined for each capability based upon realistic and viable assumptions. For example, a period of one year was assumed as the target period to achieve the desired maturity. It was considered that a longer period might prove too long in a rapidly evolving market and would result in W&B losing its competitive edge in the retail space. Elaborate the results: In this phase, the outcome of the maturity assessment was mapped to a SOA Roadmap by specifying how the gap between the As-Is and the To-Be could be addressed. The results The results of the SOA Maturity Assessment mentioned in the previous section were as shown in the following diagram: The consultancy conducting the maturity assessment identified a number of key challenges as follows: The IT department has grown immaturely while trying to constantly react to the demands placed on it by strong retail sales. Consequently, there has been a lack of overall architecture and governance, with IT developments being very tactical in nature. Each business unit within Weir & Bell Telecom has commissioned and developed its own IT systems with little regard for what had already been developed previously. Partly due to the lack of architecture and visibility over existing assets, many IT projects have been delivered late and there has been little reuse of existing assets. This has resulted in a poor perception of IT by key business stakeholders. Development teams have had little guidance; immature processes and an ill-defined software development lifecycle have resulted in estimates for development being at best optimistic and at worst poorly thought through. This has caused severe problems to the business as IT systems are continually developed late despite best intentions and lots of overtime. Poor estimation models and lack of architecture were identified as key contributors to poor planning, execution, and dependency management. SOA has not lived up to expectations with duplicate services being developed on a per-project basis with virtually no reuse of existing assets. This was attributed to the distinct lack of overall governance. In occasions, services were being overused, meaning used above the maximum throughput for which the service was designed to support. This resulted in performance penalties in the SOA infrastructure and therefore damaging the user experience. The assessment concluded that, in order to bring the current maturity level of 1.3 to the required level of 3.8, strong architecture and a new governance framework were required. This would result in other dependent disciplines being intrinsically matured (such as project management and support). The following diagram illustrates the identified health status of the different areas of Governance when compared to a Reference Governance Framework: Furthermore, the outcome of the assessment suggested that, because of a lack of overall strategy and almost nonexistent design-time and runtime governance, SOA initiatives had failed to deliver any measurable business benefits. The objectives The CIO responded to the results of the SOA Maturity Assessment by creating an enterprise architect team whose responsibility was to ensure that business needs were clearly reflected in all future IT development efforts, and that the underlying infrastructure was able to scale to meet business demands. The team was also responsible for rationalizing existing systems and services and for reducing or removing redundancy. One of the first actions for the architecture team was to create a reference architecture that specified a blueprint for all IT systems within Weir & Bell Telecom. The reference architecture supported IT agility by putting SOA at the heart of system development. This would allow the IT department to keep pace with the demands of the business moving forward and facilitate the introduction of new sales channels as identified in the business strategy for growth. The enterprise architecture team also set out clear objectives for SOA Governance. Moreover, it was concluded that, in order to achieve these objectives, appropriate tooling would be required to support the desired processes and responsibilities. While the targeted objectives of the framework were known (as it can be appreciated from the following diagram), the tools needed to support these objectives was yet to be determined. Invitations to tender were consequently sent out to the main software vendors and a selection process was undertaken to determine which could provide the infrastructure required to underpin the governance effort. A key driver for product selection was support for design-time governance, encompassing service discovery, and cataloging for reuse, dependency management, service lifecycle, and support for the enforcement of policies and standards. The product was also required to support effective runtime governance with support for a common UDDI registry, runtime policy enforcement (including security), exception handling, service deployment, and system monitoring. After an exhaustive product selection exercise, the Oracle SOA Governance Solution was chosen as the preferred software toolset to support the implementation of SOA Governance at Weir & Bell Telecom. As the preceding diagram suggests, the decision was made mainly for two reasons. Firstly, the product offering from Oracle was extremely strong at supporting design-time and runtime Governance, and therefore was highly aligned with the team's objectives for its governance effort. Secondly, as Oracle already had a considerable footprint in the technology landscape at Weir & Bell telecom, it was concluded that implementing the Oracle SOA Governance Solution would have considerable benefits as these products were certified to integrate with other Oracle Fusion Middleware products already implemented in the company, such as the Oracle SOA Suite 11g. The business case The enterprise architecture team, under the guidance of the new CIO, created a compelling business case that was presented in the board of directors at Weir & Bell Telecom. The outcome of this presentation was pivotal to transforming the image of the IT department, which was perceived as being inefficient and slow to react to business changes, and also to secure any needed funding. SOA was at the heart of the business case. The CIO recognized SOA to be the primary vehicle for introducing the agility required to meet the aggressive demands placed on the IT function by the retail arm of Weir & Bell Telecom. The maturity assessment was an essential part of the business case and it gave the CIO a real understanding of the strengths and weaknesses of his department and allowed him to focus on areas that needed to be addressed immediately. The alignment of IT strategy to business strategy was fundamental to realizing maximum return on investment (ROI) in terms of services and infrastructure. The business case, together with supporting evidence gathered during the SOA Maturity Assessment, highlighted how real synergy between IT and the business could result in automation and improvement of vital processes in the supply chain. Rationalization of the underlying infrastructure and a move to virtualization, together with the elimination of redundancy in terms of software applications and services across business units, could lead to significant cost savings across the organization. The following diagram depicts how a governed SOA implementation could significantly reduce the number of integration points and hand-offs between business units, paving the way to increased process efficiencies and cost savings: The business case discussed how the introduction of Oracle Enterprise Repository to support design-time Governance was essential to ensuring that services were rationalized across the enterprise. Better insight into existing services together with the introduction of design patterns as part of the governance effort would give rise to services that were more granular and more consumable for new processes. This in turn would allow IT to introduce new sales channels by utilizing existing services that communicated with back end order and logistics systems. It described how the reuse of service assets led to the decreased cost of development while the introduction of a new Software Development Lifecycle (SDLC) and continuous integration would lead to better quality software being produced by developers. This in turn would have a huge impact on the test department who were traditionally viewed in a bad light by management. Previously, quality was almost invariably introduced at the testing stage as testers battled with poor quality code leading to a huge testing cycle that in turn led to late delivery of software and increased costs. The Oracle Enterprise Repository combined with the Oracle Service Registry to enhance runtime Governance allowed Weir & Bell Telecom to share its services with third parties and preferred suppliers, leading to further efficiency savings in the supply chain processes. It illustrated how a large number of requisitions could be automatically raised when supplies fell below a threshold value; depending on business rules, some could even be automatically approved and sent to suppliers without human intervention. This would lead to much smoother delivery of important components and reduced component lead time while allowing the manufacturing department to have a far better control of inventory; all key factors in allowing the business to react to successful marketing and sales campaigns. Subsequent sections of the business case focused on justifying the cost of implementing governance and illustrated how the benefits would outweigh any spending in a relatively short period of time. This provided the board with key metrics for return on investment. It documented how savings could be realized in different areas. For example, on the current SOA implementation there was little or no reuse of existing services. Huge savings could be realized in the software development costs (CAPEX), by promoting code reuse by strict design-time Governance and by enforcing policies using Oracle Enterprise Repository. The business case also showed how reuse and policy enforcement would have a positive impact on operating support costs (OPEX), since with proper governance the number of services would increase gradually and not exponentially. Therefore, fewer people are required to support the services and also tasks that are usually complex, such as troubleshooting, would become more predictable since all services would implement known patterns and utilize a common exception handling framework. It is further explained that, by employing Oracle Web Services Manager (OWSM) to secure services in the production environment, the code itself could be separated from the security implementation, bringing with it the ability to declaratively define security for all service implementations, and delegate definition of security policies to the security department. OWSM also provided the ability to monitor whether SLAs were being met. Another key justification presented in the business case centered around how critical business logic embedded in old and extremely complex legacy systems could be extracted and presented as web services, and could be utilized in key value chain processes. The SOA layer would be used to provide an abstraction layer between legacy systems and the business processes themselves. This would allow the legacy applications to be replaced at a later date without having to change the process itself. The impact of change would be absorbed by the service implementation and transformation logic, the process being unaffected as the service interface would not change. This would, in turn, facilitate legacy modernization that was attractive to the board of directors and it served to illustrate how SOA could be used in different ways to deliver business benefits. Moving forward, all service implementations would be written to exacting standards to ease their consumption in the future processes and Oracle Enterprise Repository would act as a single source of truth for the SOA portfolio. Architects and analysts would be able to use the repository for version control, dependency tracking, impact analysis, and service discovery and cataloging. In short, the entire service lifecycle would be properly governed both at design-time and at runtime. The business case concluded by explaining how SOA Governance would lead to better management of the heterogeneous SOA landscape and would deliver greater visibility of end-to-end service networks and better tracking of usage, allowing the IT department to report on return on investment for SOA assets across the enterprise. All of this would ultimately transform into benefits to the business in the form of costs savings and greater flexibility. In short, a win-win situation for the business. The business case was presented to the board of directors and the feedback was very positive. The budget to begin the roadmap activities was approved. However, the board demanded that all benefits, as documented on the business case, should be supported with critical success factors that could be measured at different checkpoints throughout the SOA program. Critical success factors Based on the feedback from the board of directors, the new CIO of Weir & Bell Telecom placed the monitoring and measurement of critical success factors and business metrics at the heart of the architectural effort. By aligning the IT strategy with the business strategy and being able to report back to the board on the return on investment for IT-related projects, he would be able to demonstrate the effectiveness of IT across the enterprise. The key here was to prove that the use of SOA would result in significant cost savings while also increasing development productivity and reducing software maintenance costs. The resulting performance improvements were expected to have a significant impact on business agility and enable the organization to respond quickly to competitive challenges. The critical success factors for the architectural effort were heavily reliant on the fact that development and support costs would be reduced by enforcing governance, most notably in the reuse of existing SOA assets. The reasoning behind this proposition is explained in the following paragraphs. A SOA asset's estimated value is based on the development costs avoided by reusing rather than recreating. By reusing existing assets, an organization avoids both the costs of repeatedly developing the same functionality and the cost of maintaining different implementations of the same functionality. Thus, re-use consolidates functionality and reduces redundancy. The more that re-use occurs, the greater the savings as the diagram suggests. The difference between the time a developer would spend building an asset for single use and the time needed to use a reusable version of that asset is referred to as Predicted Net Hours Saved. This represents the development cost avoided through re-use of the asset. The following formula was used to make these calculations: Establishing the expected ROI of assets within the portfolio requires consideration of the annual usage of each asset, and the conversion of the total Predicted Net Hours Saved to a monetary value. An enterprise registry/repository with the appropriate capabilities is essential in tracking progress towards organizational SOA and re-use goals. It should be utilized to track each Asset's value, state (defined, designed, implemented, upgraded, and retired); then, as Assets are used, the registry/repository should gather the necessary data to generate reports that details an Asset's value. This provides a way for organizations to compare the estimated ROI to the actual returns in an SOA initiative. While reusable assets may vary in their size, scope, and purpose, their estimated valuation and the accurate reporting of their actual value are essential in guiding SOA Governance efforts to ensure sustainable alignment with business goals. SOA Governance is essential for increasing the value of assets by insuring their alignment with and support of policies and standards as established at the architectural, IT, and corporate levels. An asset's value is determined not solely by its reusability or re-use, but also by the contribution it makes in moving the organization toward its business goals. To that end, the importance of effective SOA lifecycle governance in guiding the design, development, support, and retirement of assets cannot be overstated. A new reference architecture The enterprise architecture team began by creating a new reference architecture that would be strongly aligned to the business strategy. This is presented in the following diagram: The IT strategy was developed with the target operating model in mind including the requirement for new sales channels. The underlying infrastructure was ported to a private cloud-based model to allow for the rapid growth predicted by the business and also in light of expected acquisitions that were due to be made over the coming years. SOA was endorsed as the preferred architectural style for software development with existing and new commercially available and off-the-shelf (COTS) products having little or no customizations moving forward. Proposed IT developments were assessed and aligned to the IT strategy with a number of projects scrapped and new initiatives introduced. The new governance process A new governance process was introduced across the enterprise to reduce redundancy of all software development efforts between business units. A clearly defined SOA Roadmap was created indicating how the current state of the IT organization could move as efficiently as possible to the new To-Be model. A whole suite of governance standards was created, documented, and distributed to the development teams. These standards clearly specified the development, programming, and deployment standards that were to be adopted for all SOA initiatives enterprise wide. Design-time governance was introduced, covering all aspects of service discovery, design, versioning, and decommissioning. The Oracle Enterprise Repository was introduced to support design-time Governance by ensuring that all service metadata and XML artifacts were accessible across the enterprise in an effort to promote re-use, and therefore to ensure that key benefits were realized from existing investment in services. Oracle Enterprise Repository was also used to harvest assets enterprise-wide, ensuring that existing investment was not lost as part of the governance initiative. Oracle JDeveloper was already used by the development teams for creating services. Integration of the JDeveloper SOA development environment with the Repository and Service Registry was seen as a key requirement to enable developers to access and synchronize between the repository and the development environment to automatically harvest assets and enhance productivity. Runtime governance standards were defined and documented. A new deployment framework was created to standardize system set up and service deployment. This would enable IT infrastructure to grow efficiently as the business demands increased. Oracle Service Registry was introduced to facilitate rapid discovery and consumption of existing services. Improved visibility Another key recommendation highlighted as part of the SOA Maturity Assessment was the requirement to improve runtime visibility of SOA assets. As a result, the runtime engines (such as the Oracle Service Registry and Oracle Enterprise Manager) were integrated with Oracle Enterprise Repository to ensure that key metrics around service utilization and service re-use were feedback into the asset's details page. Having design-time and runtime systems integrated, empowered project managers, SOA architects, and designers to enforce policies around service re-use, which ultimately accounted in savings to the company. Standardized error reporting and system monitoring was introduced with Oracle Enterprise Manager (OEM) being adopted across the enterprise. Business Activity Monitoring (BAM) was also introduced on selected business processes, following a review of business metrics and key performance indicators with the business. Oracle BAM and OEM gave the support team increased visibility into application performance and availability, allowing them to more proactively monitor problems and suggest improvements to a number of key business processes. In some cases, process lifecycles were decreased by as much as 60 percent and cost savings in one area ran into thousands of pounds. This exercise rapidly improved the availability of essential services and processes, which in turn provided a genuine real good factor to the business. The latter was important as the board started to fund further process improvement projects. Furthermore, continuous integration was implemented so that software was tested regularly ensuring that the quality of software was much higher than had previously been the case. The SOA Roadmap highlighted further areas of business automation and senior business executives were able to understand and digest how IT could now work hand in hand with the business to introduce real cost savings and to streamline the supply chain further. The exercise conducted for identifying key business metrics and KPIs also helped the business to focus on important processes that were key to the success of Weir & Bell Telecom. Understanding the business metrics helped the stakeholders to stop and realize a number of business improvements particularly in areas where previously hand-offs between business units were creating unnecessary delays and inefficiencies. Very importantly, IT and the business now had the ability to measure, qualitatively and quantitatively, key business areas, allowing the board for the first time to have a real understanding of the impact of IT investment moving forward. This could range from bottom line costs savings to simply improving the lives of some of its staff by freeing them from tasks that could otherwise be automated, thus freeing them up for more value-added activities. Summary In this article we described a case study based on a real live SOA Governance implementation as experienced by the authors. The article illustrated how the governance concepts such as maturity assessments, reference architectures, SOA assets, and design-time and runtime Governance, were put into practice in order to successfully implement SOA Governance into an organization. This article emphasized the importance of having the right level of sponsorship and buy-in from the business before embarking on a governance implementation. This was achieved up front, since without business sponsorship the benefits that SOA can bring to the table would have not been visible or achievable. Additionally, the article described how by presenting a business case with clear business benefits and objectives it was possible to qualitatively and quantitatively measure success. This in turn allowed the board of directors to understand the positive impact that IT and SOA can bring to business. The article concluded by describing how the Oracle SOA Governance toolset was implemented alongside the company's existing Oracle SOA and technological landscape in order to deliver design-time and runtime Governance. Resources for Article: Further resources on this subject: Oracle Integration and Consolidation Products [Article] SOA Application Design [Article] Process Driven SOA Development [Article]
Read more
  • 0
  • 0
  • 5737

article-image-reporting-based-ssrs
Packt
25 Sep 2013
5 min read
Save for later

Reporting Based on SSRS

Packt
25 Sep 2013
5 min read
(For more resources related to this topic, see here.) Creating a matrix report A matrix is an interesting representation format with a two-dimensional view of the data, allowing capabilities to consolidate by row and column. This recipe will discuss how to add and use a matrix data region in reports. Also discussed is the totaling capabilities in matrix reports. How to do it… This recipe is broken down into two sections. In the basic report design section we will build a simple RDP that will be used in this recipe as well as in other recipes found in this article and the actual recipe is in the second section. Basic report design Before we start on this recipe we will build an RDP class that can be used as a source for all the recipes in this article. This RDP will be used as the source of a dataset for all the following reports. Create a query as seen here. The InventItemGroupItem table uses the exists join and is added for the purpose of limiting the sales lines data to certain item groups. The goal of the RDP is to run across the sales line in the system and then retrieve the item, item group, and the shipping date confirmed. The shipping date confirmed is also split into multiple parts such as years, months, and days. This RDP can be time consuming if you have a huge database of sales orders, so limit your data to certain item groups or a certain period as required in the RDP's processReport method. This RDP will fill a temporary table shown here: The RDP shown here will fill the temporary table by running through all the sales lines in the system. The general approach for analysis like this is to use OLAP so that it is faster and provides multiple dimensions of consolidations but using an OLAP to demonstrate these report controls might stop several from practicing. This is because the majority of AX developers are not BI experts. Keeping this in mind this RDP has been used to demonstrate the examples. [ //bind query - shows in the report dialog SRSReportQueryAttribute(queryStr(PktSalesLine)) ] class PktItemSalesHistoryDP extends SRSReportDataProviderBase { PktItemSalesHistoryTmp salesHistoryTmp; } [ SRSReportDataSetAttribute(tableStr(PktItemSalesHistoryTmp)) ] public PktItemSalesHistoryTmp getItemSalesHistoryTmp() { select salesHistoryTmp; return salesHistoryTmp; } private void insertTmpTable(SalesLine _salesLine) { Qty qty; date shipDate; InventItemGroupItem groupItem; qty = _salesLine.QtyOrdered; shipDate = _salesLine.ShippingDateConfirmed; groupItem = InventItemGroupItem::findByItemIdLegalEntity( _salesLine.ItemId, _salesLine.DataAreaId); salesHistoryTmp.clear(); salesHistoryTmp.ItemId = _salesLine.ItemId; salesHistoryTmp.ItemGroupId = groupItem.ItemGroupId; salesHistoryTmp.Price = _salesLine.salesPrice; salesHistoryTmp.Amount = _salesLine.SalesPrice * Qty; salesHistoryTmp.Qty = qty; salesHistoryTmp.Year = year(shipDate); salesHistoryTmp.MonthOfYearId = mthOfYr(shipDate); salesHistoryTmp.Days = dayOfMth(shipDate); salesHistoryTmp.insert(); } [ SysEntryPointAttribute(false) ] public void processReport() { Query query; QueryRun queryRun; SalesLine salesLine; InventItemGroupItem itemGroup; query = this.parmQuery(); queryRun = new queryRun(query); while (queryRun.next()) { salesLine = queryRun.get(tableNum(salesLine)); this.insertTmpTable(salesLine); } } Creating a matrix report Create a report in Visual Studio named PktMatrixReport and add the RDP provider as a dataset. Set the Dynamic filter property to false. Create a new precision design and name it matrixDesign, and then double-click to open up the editor. Right-click and insert a new matrix data region: Use the field selector to set the fields as shown in the following screenshot. Choosing Qty in the data section will automatically add the Sum function to it: To add the total quantity for each row, on the Row Groups option at the bottom, click on the small arrow and then navigate to Add Totals | After. To add the total quantity for each column, on the Column Groups option at the bottom, click on the small arrow and then navigate to Add Totals | After. There are three total boxes in the design. Each represent the row total, column total, and the grand total. Grand total tallies the sum of rows and sum of columns. As you can see in the following screenshot that the grand total block in the title row is colored and the font is also set to bold. This will give a better appearance for the matrix: The header for the row is present but there is no similar header for the column group. So right-click on the first column and navigate to Insert Row | Outside Group – Above. This will give a header for the column. Enter the expression string ItemGroupId using the label ID or the static text. The design appears as shown here: Save the report and preview it: How it works… A matrix data region is actually a Tablix control behind the hood. The Tablix control combines the behavior of table, list, and matrix reports. Though the UI has table, matrix, and list controls, they are the same controls under the hood; they open up with a different configuration. The matrix data region has both row and column group, whereas a table control has only column group. Matrix helps create summary type reports.
Read more
  • 0
  • 0
  • 1745

article-image-vaadin-and-its-context
Packt
25 Sep 2013
24 min read
Save for later

Vaadin and its Context

Packt
25 Sep 2013
24 min read
(For more resources related to this topic, see here.) Developing Java applications and more specifically, developing Java web applications should be fun. Instead, most projects are a mess of sweat and toil, pressure and delays, costs and cost cutting. Web development has lost its appeal. Yet, among the many frameworks available, there is one in particular that draws our attention because of its ease of use and its original stance. It has been around since the past decade and has begun to grow in importance. The name of this framework is Vaadin. The goal of this article is to see, step-by-step, how to develop web applications with Vaadin. Vaadin is the Finnish word for a female reindeer (as well as a Finnish goddess). This piece of information will do marvels to your social life as you are now one of the few people on Earth who know this (outside Finland). Before diving right into Vaadin, it is important to understand what led to its creation. Readers who already have this information (or who don't care) should go directly to Environment Setup. Rich applications Vaadin is often referred to as a Rich Internet Application (RIA) framework. Before explaining why, we need to first define some terms which will help us describe the framework. In particular, we will have a look at application tiers, the different kind of clients, and their history. Application tiers Some software run locally, that is, on the client machine and some run remotely, such as on a server machine. Some applications also run on both the client and the server. For example, when requesting an article from a website, we interact with a browser on the client side but the order itself is passed on a server in the form of a request. Traditionally, all applications can be logically separated into tiers, each having different responsibilities as follows: Presentation : The presentation tier is responsible for displaying the end-user information and interaction. It is the realm of the user interface. Business Logic : The logic tier is responsible for controlling the application logic and functionality. It is also known as the application tier, or the middle tier as it is the glue between the other two surrounding tiers, thus leading to the term middleware. Data : The data tier is responsible for storing and retrieving data. This backend may be a file system. In most cases, it is a database, whether relational, flat, or even an object-oriented one. This categorization not only naturally corresponds to specialized features, but also allows you to physically separate your system into different parts, so that you can change a tier with reduced impact on adjacent tiers and no impact on non-adjacent tiers. Tier migration In the histor yof computers and computer software, these three tiers have moved back and forth between the server and the client. Mainframes When computers were mainframes, all tiers were handled by the server. Mainframes stored data, processed it, and were also responsible for the layout of the presentation. Clients were dumb terminals, suited only for displaying characters on the screen and accepting the user input. Client server Not many companies could afford the acquisition of a mainframe (and many still cannot). Yet, those same companies could not do without computers at all, because the growing complexity of business processes needed automation. This development in personal computers led to a decrease in their cost. With the need to share data between them, the network traffic rose. This period in history saw the rise of the personal computer, as well as the Client server term, as there was now a true client. The presentation and logic tier moved locally, while shared databases were remotely accessible, as shown in the following diagram: Thin clients Big companies migrating from mainframes to client-server architectures thought that deploying software on ten client machines on the same site was relatively easy and could be done in a few hours. However, they quickly became aware of the fact that with the number of machines growing in a multi-site business, it could quickly become a nightmare. Enterprises also found that it was not only the development phase that had to be managed like a project, but also the installation phase. When upgrading either the client or the server, you most likely found that the installation time was high, which in turn led to downtime and that led to additional business costs. Around 1991, Sir Tim Berners-Leeinvented the Hyper Text Markup Language, better known as HTML. Some time after that, people changed its original use, which was to navigate between documents, to make HTML-based web applications. This solved the deployment problem as the logic tier was run on a single-server node (or a cluster), and each client connected to this server. A deployment could be done in a matter of minutes, at worst overnight, which was a huge improvement. The presentation layer was still hosted on the client, with the browser responsible for displaying the user interface and handling user interaction. This new approach brought new terms, which are as follows: The old client-server architecture was now referred to as fat client . The new architecture was coined as thin client, as shown in the following diagram: Limitations of the thin-client applications approach Unfortunately, this evolution was made for financial reasons and did not take into account some very important drawbacks of the thin client. Poor choice of controls HTML does not support many controls, and what is available is not on par with fat-client technologies. Consider, for example, the list box: in any fat client, choices displayed to the user can be filtered according to what is typed in the control. In legacy HTML, there's no such feature and all lines are displayed in all cases. Even with HTML5, which is supposed to add this feature, it is sadly not implemented in all browsers. This is a usability disaster if you need to display the list of countries (more than 200 entries!). As such, ergonomics of true thin clients have nothing to do with their fat-client ancestors. Many unrelated technologies Developers of fat-client applications have to learn only two languages: SQL and the technology's language, such as Visual Basic, Java, and so on. Web developers, on the contrary, have to learn an entire stack of technologies, both on the client side and on the server side. On the client side, the following are the requirements: First, of course, is HTML. It is the basis of all web applications, and although some do not consider it a programming language per se, every web developer must learn it so that they can create content to be displayed by browsers. In order to apply some common styling to your application, one will probably have to learn the Cascading Style Sheets ( CSS) technology. CSS is available in three main versions, each version being more or less supported by browser version combinations (see Browser compatibility). Most of the time, it is nice to have some interactivity on the client side, like pop-up windows or others. In this case, we will need a scripting technology such as ECMAScript. ECMAScript is the specification of which JavaScript is an implementation (along with ActionScript ). It is standardized by the ECMA organization. See http://www.ecma-international.org/publications/standards/Ecma-262.htm for more information on the subject. Finally, one will probably need to update the structure of the HTML page, a healthy dose of knowledge of the Document Object Model (DOM) is necessary. As a side note, consider that HTML, CSS, and DOM are W3C specifications while ECMAScript is an ECMA standard. From a Java point-of-view and on the server side, the following are the requirements: As servlets are the most common form of request-response user interactions in Java EE, every web developer worth his salt has to know both the Servlet specification and the Servlet API. Moreover, most web applications tend to enforce the Model-View-Controller paradigm. As such, the Java EE specification enforces the use of servlets for controllers and JavaServer Pages (JSP ) for views. As JSP are intended to be templates, developers who create JSP have an additional syntax to learn, even though they offer the same features as servlets. JSP accept scriptlets, that is, Java code snippets, but good coding practices tend to frown upon this, however, as Java code can contain any feature, including some that should not be part of views—for example, the database access code. Therefore, a completely new technology stack is proposed in order to limit code included in JSP: the tag libraries. These tag libraries also have a specification and API, and that is another stack to learn. However, these are a few of the standard requirements that you should know in order to develop web applications in Java. Most of the time, in order to boost developer productivity, one has to use frameworks. These frameworks are available in most of the previously cited technologies. Some of them are supported by Oracle, such as Java Server Faces, others are open source, such as Struts. JavaEE 6 seems to favor replacement of JSP and Servlet by Java Server Faces(JSF). Although JSF aims to provide a component-based MVC framework, it is plagued by a relative complexity regarding its components lifecycle. Having to know so much has negative effects, a few are as follows: On the technical side, as web developers have to manage so many different technologies, web development is more complex than fat-client development, potentially leading to more bugs On the human resources side, different meant either different profiles were required or more resources, either way it added to the complexity of human resource management On the project management side, increased complexity caused lengthier projects: developing a web application was potentially taking longer than developing a fat-client application All of these factors tend to make the thin-client development cost much more than fat-client, albeit the deployment cost was close to zero. Browser compatibility The Web has standards, most of them upheld by the World Wide Web Consortium. Browsers more or less implement these standards, depending on the vendor and the version. The ACID test, in version 3, is a test for browser compatibility with web standards. Fortunately, most browsers pass the test with 100 percent success, which was not the case two years ago. Some browsers even make the standards evolve, such as Microsoft which implemented the XmlHttpRequest objectin Internet Explorer and thus formed the basis for Ajax. One should be aware of the combination of the platform, browser, and version. As some browsers cannot be installed with different versions on the same platform, testing can quickly become a mess (which can fortunately be mitigated with virtual machines and custom tools like http://browsershots.org). Applications should be developed with browser combinations in mind, and then tested on it, in order to ensure application compatibility. For intranet applications, the number of supported browsers is normally limited. For Internet applications, however, most common combinations must be supported in order to increase availability. If this wasn't enough, then the same browser in the same version may run differently on different operating systems. In all cases, each combination has an exponential impact on the application's complexity, and therefore, on cost. Page flow paradigm Fat-client applications manage windows. Most of the time, there's a main window. Actions are mainly performed in this main window, even if sometimes managed windows or pop-up windows are used. As web applications are browser-based and use HTML over HTTP, things are managed differently. In this case, the presentation unit is not the window but the page. This is a big difference that entails a performance problem: indeed, each time the user clicks on a submit button, the request is sent to the server, processed by it, and the HTML response is sent back to the client. For example, when a client submits a complex registration form, the entire page is recreated on the server side and sent back to the browser even if there is a minor validation error, even though the required changes to the registration form would have been minimal. Beyond the limits Over the last few years, users have been applying some pressure in order to have user interfaces that offer the same richness as good old fat-client applications. IT managers, however, are unwilling to go back to the old deploy-as-a-project routine and its associated costs and complexity. They push towards the same deployment process as thin-client applications. It is no surprise that there are different solutions in order to solve this dilemma. What are rich clients? All the following solutions are globally called rich clients, even if the approach differs. They have something in common though: all of them want to retain the ease of deployment of the thin client and solve some or all of the problems mentioned previously. Rich clients fulfill the fourth quadrant of the following schema, which is like a dream come true, as shown in the following diagram: Some rich client approaches The following solutions are strategies that deserve the rich client label. Ajax Ajax was one of the first successful rich-client solutions. The term means Asynchronous JavaScript with XML. In effect, this browser technology enables sending asynchronous requests, meaning there is no need to reload the full page. Developers can provide client scripts implementing custom callbacks: those are executed when a response is sent from the server. Most of the time, such scripts use data provided in the response payload to dynamically update relevant part of the page DOM. Ajax addresses the richness of controls and the page flow paradigm. Unfortunately: It aggravates browser-compatibility problems as Ajax is not handled in the same way by all browsers. It has problems unrelated directly to the technologies, which are as follows: Either one learns all the necessary technologies to do Ajax on its own, that is, JavaScript, Document Object Model, and JSON/XML, to communicate with the server and write all common features such as error handling from scratch. Alternatively, one uses an Ajax framework, and thus, one has to learn another technology stack. Richness through a plugin The oldest way to bring richness to the user's experience is to execute the code on the client side and more specifically, as a plugin in the browser. Sun—now Oracle—proposed the applet technology, whereas Microsoft proposed ActiveX. The latest technology using this strategy is Flash. All three were failures due to technical problems, including performance lags, security holes, and plain-client incompatibility or just plain rejection by the market. There is an interesting way to revive the applet with the Apache Pivot project, as shown in the following screenshot (http://pivot.apache.org/), but it hasn't made a huge impact yet; A more recent and successful attempt at executing code on the client side through a plugin is through Adobe's Flex. A similar path was taken by Microsoft's Silverlight technology. Flex is a technology where static views are described in XML and dynamic behavior in ActionScript. Both are transformed at compile time in Flash format. Unfortunately, Apple refused to have anything to do with the Flash plugin on iOS platforms. This move, coupled with the growing rise of HTML5, resulted in Adobe donating Flex to the Apache foundation. Also, Microsoft officially renounced plugin technology and shifted Silverlight development to HTML5. Deploying and updating fat-client from the web The most direct way toward rich-client applications is to deploy (and update) a fat-client application from the web. Java Web Start Java Web Start (JWS), available at http://download.oracle.com/javase/1.5.0/docs/guide/javaws/, is a proprietary technology invented by Sun. It uses a deployment descriptor in Java Network Launching Protocol (JNLP) that takes the place of the manifest inside a JAR file and supplements it. For example, it describes the main class to launch the classpath, and also additional information such as the minimum Java version, icons to display on the user desktop, and so on. This descriptor file is used by the javaws executable, which is bundled in the Java Runtime Environment. It is the javaws executable's responsibility to read the JNLP file and do the right thing according to it. In particular, when launched, javaws will download the updated JAR. The detailed process goes something like the following: The user clicks on a JNLP file. The JNLP file is downloaded on the user machine, and interpreted by the local javaws application. The file references JARs that javaws can download. Once downloaded, JWS reassembles the different parts, create the classpath, and launch the main class described in the JNLP. JWS correctly tackles all problems posed by the thin-client approach. Yet it never reaches critical mass for a number of reasons: First time installations are time-consuming because typically lots of megabytes need to be transferred over the wire before the users can even start using the app. This is a mere annoyance for intranet applications, but a complete no go for Internet apps. Some persistent bugs weren't fixed across major versions. Finally, the lack of commercial commitment by Sun was the last straw. A good example of a successful JWS application is JDiskReport (http://www.jgoodies.com/download/jdiskreport/jdiskreport.jnlp), a disk space analysis tool by Karsten Lentzsch , which is available on the Web for free. Update sites Updating software through update sites is a path taken by both Integrated Development Environment ( IDE ) leaders, NetBeans and Eclipse. In short, once the software is initially installed, updates and new features can be downloaded from the application itself. Both IDEs also propose an API to build applications. This approach also handles all problems posed by the thin-client approach. However, like JWS, there's no strong trend to build applications based on these IDEs. This can probably be attributed to both IDEs using the OSGI standard whose goal is to address some of Java's shortcomings but at the price of complexity. Google Web Toolkit Google Web Toolkit (GWT) is the framework used by Google to create some of its own applications. Its point of view is very unique among the technologies presented here. It lets you develop in Java, and then the GWT compiler transforms your code to JavaScript, which in turn manipulates the DOM tree to update HTML. It's GWT's responsibility to handle browser compatibility. This approach also solves the other problems of the pure thin-client approach. Yet, GWT does not shield developers from all the dirty details. In particular, the developer still has to write part of the code handling server-client communication and he has to take care of the segregation between Java server-code which will be compiled into byte code and Java client-code which will be compiled into JavaScript. Also, note that the compilation process may be slow, even though there are a number of optimization features available during development. Finally, developers need a good understanding of the DOM, as well as the JavaScript/DOM event model. Why Vaadin? Vaadin is a solution evolved from a decade of problem-solving approach, provided by a Finnish company named Vaadin Ltd, formerly IT Mill. Therefore, having so many solutions available, could question the use of Vaadin instead of Flex or GWT? Let's first have a look at the state of the market for web application frameworks in Java, then detail what makes Vaadin so unique in this market. State of the market Despite all the cons of the thin-client approach, an important share of applications developed today uses this paradigm, most of the time with a touch of Ajax augmentation. Unfortunately, there is no clear leader for web applications. Some reasons include the following: Most developers know how to develop plain old web applications, with enough Ajax added in order to make them usable by users. GWT, although new and original, is still complex and needs seasoned developers in order to be effective. From a Technical Lead or an IT Manager's point of view, this is a very fragmented market where it is hard to choose a solution that will meet users' requirements, as well as offering guarantees to be maintained in the years to come. Importance of Vaadin Vaadin is a unique framework in the current ecosystem; its differentiating features include the following: There is no need to learn different technology stacks, as the coding is solely in Java. The only thing to know beside Java is Vaadin's own API, which is easy to learn. This means: The UI code is fully object-oriented There's no spaghetti JavaScript to maintain It is executed on the server side Furthermore, the IDE's full power is in our hands with refactoring and code completion. No plugin to install on the client's browser, ensuring all users that browse our application will be able to use it as-is. As Vaadin uses GWT under the hood, it supports all browsers that the version of GWT also supports. Therefore, we can develop a Vaadin application without paying attention to the browsers and let GWT handle the differences. Our users will interact with our application in the same way, whether they use an outdated version (such as Firefox 3.5), or a niche browser (like Opera). Moreover, Vaadin uses an abstraction over GWT so that the API is easier to use for developers. Also, note that Vaadin Ltd (the company) is part of GWT steering committee, which is a good sign for the future. Finally, Vaadin conforms to standards such as HTML and CSS, making the technology future proof. For example, many applications created with Vaadin run seamlessly on mobile devices although they were not initially designed to do so. Vaadin integration In today's environment, integration features of a framework are very important, as normally every enterprise has rules about which framework is to be used in some context. Vaadin is about the presentation layer and runs on any servlet container capable environment. Integrated frameworks There are three integration levels possible which are as follows: Level 1 : out-of-the-box or available through an add-on, no effort required save reading the documentation Level 2 : more or less documented Level 3 : possible with effort The following are examples of such frameworks and tools with their respective integration estimated effort: Level 1 : Java Persistence API ( JPA ): JPA is the Java EE 5 standard for all things related to persistence. An add-on exists that lets us wire existing components to a JPA backend. Other persistence add-ons are available in the Vaadin directory, such as a container for Hibernate, one of the leading persistence frameworks available in the Java ecosystem. A bunch of widget add-ons, such as tree tables, popup buttons, contextual menus, and many more. Level 2 : Spring is a framework which is based on Inversion of Control ( IoC ) that is the de facto standard for Dependency Injection. Spring can easily be integrated with Vaadin, and different strategies are available for this. Context Dependency Injection ( CDI ): CDI is an attempt at making IoC a standard on the Java EE platform. Whatever can be done with Spring can be done with CDI. Any GWT extensions such as Ext-GWT or Smart GWT can easily be integrated in Vaadin, as Vaadin is built upon GWT's own widgets. Level 3 : We can use another entirely new framework and languages and integrate them with Vaadin, as long as they run on the JVM: Apache iBatis, MongoDB, OSGi, Groovy, Scala, anything you can dream of! Integration platforms Vaadin provides an out-of-the-box integration with an important third-party platform: Liferay is an open source enterprise portal backed by Liferay Inc. Vaadin provides a specialized portlet that enables us to develop Vaadin applications as portlets that can be run on Liferay. Also, there is a widgetset management portlet provided by Vaadin, which deploys nicely into Liferay's Control Panel. Using Vaadin in the real world If you embrace Vaadin, then chances are that you will want to go beyond toying with the Vaadin framework and develop real-world applications. Concerns about using a new technology Although it is okay to use the latest technology for a personal or academic project, projects that have business objectives should just run and not be riddled with problems from third-party products. In particular, most managers may be wary when confronted by anew product (or even a new version), and developers should be too. The following are some of the reasons to choose Vaadin: Product is of highest quality : The Vaadin team has done rigorous testing throughout their automated build process. Currently, it consists of more than 8,000 unit tests. Moreover, in order to guarantee full compatibility between versions, many (many!) tests execute pixel-level regression testing. Support : Commercial : Although completely committed to open source, Vaadin Limited offer commercial support for their product. Check their Pro Account offering. User forums : A Vaadin user forum is available. Anyone registered can post questions and see them answered by a member of the team or of the community. Note that Vaadin registration is free, as well as hassle-free: you will just be sent the newsletter once a month (and you can opt-out, of course). Retro-compatibility: API : The server-side API is very stable, version after version, and has survived major client-engines rewrite. Some part of the API has been changed from v6 to v7, but it is still very easy to migrate. Architecture : Vaadin's architecture favors abstraction and is at the root of it all. Full-blown documentation available : Product documentation : Vaadin's site provides three levels of documentation regarding Vaadin: a five-minute tutorial, a one-hour tutorial, and the famed article of Vaadin . Tutorials API documentation : The Javadocs are available online; there is no need to build the project locally. Course/webinar offerings : Vaadin Ltd currently provides four different courses, which tackles all the needed skills for a developer to be proficient in the framework. Huge community around the product : There is a community gathering, which is ever growing and actively using the product. There are plenty of blogs and articles online on Vaadin. Furthermore, there are already many enterprises using Vaadin for their applications. Available competent resources : There are more and more people learning Vaadin. Moreover, if no developer is available, the framework can be learned in a few days. Integration with existing product/platforms : Vaadin is built to be easily integrated with other products and platforms. The artile of Vaadin describes how to integrate with Liferay and Google App Engine. Others already use Vaadin Upon reading this, managers and developers alike should realize Vaadin is mature and is used on real-world applications around the world. If you still have any doubts, then you should check http://vaadin.com/who-is-using-vaadin and be assured that big businesses trusted Vaadin before you, and benefited from its advantages as well. Summary In this article, we saw the migration of application tiers in the software architecture between the client and the server. We saw that each step resolved the problems in the previous architecture: Client-server used the power of personal computers in order to decrease mainframe costs Thin-clients resolved the deployment costs and delays Thin-clients have numerous drawbacks. For the user, a lack of usability due to poor choice of controls, browser compatibility issues, and the navigation based on page flow; for the developer, many technologies to know. As we are at the crossroad, there is no clear winner in all the solutions available: some only address a few of the problems, some aggravate them. Vaadin is an original solution that tries to resolve many problems at once: It provides rich controls It uses GWT under the cover that addresses most browser compatibility issues It has abstractions over the request response model, so that the model used is application-based and not page based The developer only needs to know one programming language: Java, and Vaadin generates all HTML, JavaScript, and CSS code for you Now we can go on and create our first Vaadin application! Resources for Article : Further resources on this subject: Vaadin Portlets in Liferay User Interface Development [Article] Creating a Basic Vaadin Project [Article] Vaadin – Using Input Components and Forms [Article]
Read more
  • 0
  • 0
  • 4495
article-image-deploying-vertx-application
Packt
24 Sep 2013
12 min read
Save for later

Deploying a Vert.x application

Packt
24 Sep 2013
12 min read
(For more resources related to this topic, see here.) Setting up an Ubuntu box We are going to set up an Ubuntu virtual machine using the Vagrant tool. This virtual machine will simulate a real production server. If you already have an Ubuntu box (or a similar Linux box) handy, you can skip this step and move on to setting up a user. Vagrant (http://www.vagrantup.com/) is a tool for managing virtual machines. Many people use it to manage their development environments so that they can easily share them and test their software on different operating systems. For us, it is a perfect tool to practice Vert.x deployment into a Linux environment. Install Vagrant by heading to the Downloads area at http://vagrantup.com and selecting the latest version. Select a package for your operating system and run the installer. Once it is done you should have a vagrant command available on the command line as follows: vagrant –v Navigate to the root directory of our project and run the following command: vagrant init precise64 http://files.vagrantup.com/precise64.box This will generate a file called Vagrant file in the project folder. It contains configuration for the virtual machine we're about to create. We initialized a precise64 box, which is shorthand for the 64-bit version of Ubuntu 12.04 Precise Pangolin. Open the file in an editor and find the following line: # config.vm.network :private_network, ip: "192.168.33.10" Uncomment the line by removing the # character. This will enable private networking for the box. We will be able to conveniently access it with the IP address 192.168.33.10 locally. Run the following command to download, install, and launch the virtual machine: vagrant up This command launches the virtual machine configured in the Vagrantfile. On first launch it will also download it. Because of this, running the command may take a while. Once the command is finished you can check the status of the virtual machine by running vagrant status, suspend it by running vagrant suspend, bring it back up by running vagrant up, and remove it by running vagrant destroy. Setting up a user For any application deployment, it's a good idea have an application-specific user configured. The sole purpose of the user is to run the application. This gives you a nice way to control permissions and make sure the application can only do what it's supposed to. Open a shell connection to our Linux box. If you followed the steps to set up a Vagrant box, you can do this by running the following command in the project root directory: vagrant ssh Add a new user called mindmaps using the following command: sudo useradd -d /home/mindmaps -m mindmaps Also specify a password for the new user using the following command (and make a note of the password you choose; you'll need it): sudo passwd mindmaps Install Java on the server Install Java for the Linux box, as described in Getting Started with Vert.x. As a quick reminder, Java can be installed on Ubuntu with the following command: sudo apt-get install openjdk-7-jdk On fresh Ubuntu installations, it is a good idea to always make sure the package manager index is up-to-date before installing any packages. This is also the case for our Ubuntu virtual machine. Run the following command if the Java installation fails: sudo apt-get update Installing MongoDB on the server We also need MongoDB to be installed on the server, for persisting the mind maps. Setting up privileged ports Our application is configured to serve requests on port 8080. When we deploy to the Internet, we don't want users to have to know anything about ports, which means we should deploy our app to the default HTTP port 80 instead. On Unix systems (such as Linux) port 80 can only be bound to by the root user. Because it is not a good idea to run applications as the root user, we should set up a special privilege for the mindmaps user to bind to port 80. We can do this with the authbind utility. authbind is a Linux utility that can be used to bind processes to privileged ports without requiring root access. Install authbind using the package manager with the following command: sudo apt-get install authbind Set up a privilege for the mindmaps user to bind to port 80, by creating a file into the authbind configuration directory with the following command: cd /etc/authbind/byport/sudo touch 80sudo chown mindmaps:mindmaps 80sudo chmod 700 80 When authbind is run, it checks from this directory, whether there is a file corresponding to the used port and whether the current user has access to it. Here we have created such a file. Many people prefer to have a web server such as Nginx or Apache as a frontend and not expose backend services to the Internet directly. This can also be done with Vert.x. In that case, you could just deploy Vert.x to port 8080 and skip the authbind configuration. Then, you would need to configure reverse proxying for the Vert.x application in your web server. Note that we are using the event bus bridge in our application, and that uses HTTP WebSockets as the transport mechanism. This means the front-end web server must be able to also proxy WebSocket traffic. Nginx is able to do this starting from version 1.3 and Apache from version 2.4.5. Installing Vert.x on the server Switch to the mindmaps user in the shell on the virtual machine using the following command: sudo su – mindmaps Install Vert.x for this user, as described in Getting Started with Vert.x. As a quick reminder, it can be done by downloading and unpacking the latest distribution from http://vertx.io. Making the application port configurable Let's move back to our application code for a moment. During development we have been running the application in port 8080, but on the server we will want to run it in port 80. To support both of these scenarios we can make the port configurable through an environment variable. Vert.x makes environment variables available to verticles through the container API. In JavaScript, the variables can be found in the container.env object. Let's use it to give our application a port at runtime. Find the following line from the deployment verticle app.js: port: 8080, Change it to the following line: port: parseInt(container.env.get('MINDMAPS_PORT')) || 8080, This gets the MINDMAPS_PORT environment variable, and parses it from a string to an integer using the standard JavaScript parseInt function. If no port has been given, the default value 8080 is used. We also need to change the host configuration of the web server. So far, we have been binding to localhost, but now we also want the application to be accessible from outside the server. Find the following line in app.js: host: "localhost", Change it to the following line: host: "0.0.0.0", Using the host 0.0.0.0 will make the server bind to all IPv4 network interfaces the server has. Setting up the application on the server We are going to need some way of transferring the application code itself to the server, as well as delivering incremental updates as new versions of the application are developed. One of the simplest ways to accomplish this is to just transfer the application files over using the rsync tool, which is what we will do. rsync is a widely used Unix tool for transferring files between machines. It has some useful features over plain file copying, such as only copying the deltas of what has changed, and two-way synchronization of files. Create a directory for the application, on the home directory of the mindmaps user using the following command: mkdir ~/app Go back to the application root directory and transfer the files from it to the new remote directory: rsync -rtzv . mindmaps@192.168.33.10:~/app Testing the setup At this point, the project working tree should already be in the application directory on the remote server, because we have transferred it over using rsync. You should also be able to run it on the virtual machine, provided that you have the JDK, Vert.x, and MongoDB installed, and that you have authbind installed and configured. You can run the app with the following commands: cd ~/appJAVA_OPTS="-Djava.net.preferIPv4Stack=true" MINDMAPS_PORT=80 authbind ~/vert.x-2.0.1-final/bin/vertx run app.js Let's go through the file bit by bit as follows: We pass a Java system parameter called java.net.preferIPv4Stack to Java via the JAVA_OPTS environment variable. This will have Java use IPv4 networking only. We need it because the authbind utility only supports IPv4. We also explicitly set the application to use port 80 using the MINDMAPS_PORT environment variable. We wrap the Vert.x command with the authbind command. Finally, there's the call to Vert.x. Substitute the path to the Vert.x executable with the path you installed Vert.x to. After starting the application, you should be able to see it by navigating to //192.168.33.10 in a browser. Setting up an upstart service We have our application fully operational, but it isn't very convenient or reliable to have to start it manually. What we'll do next is to set up an Ubuntu upstart job that will make sure the application is always running and survives things like server restarts. Upstart is an Ubuntu utility that handles task supervision and automated starting and stopping of tasks when the machine starts up, shuts down, or when some other events occur. It is similar to the /sbin/init daemon, but is arguably easier to configure, which is the reason we'll be using it. The first thing we need to do is set up an upstart configuration file. Open an editor with root access (using sudo) for a new file /etc/init/mindmaps.conf, and set its contents as follows: start on runlevel [2345]stop on runlevel [016]setuid mindmapssetgid mindmapsenv JAVA_OPTS="-Djava.net.preferIPv4Stack=true"env MINDMAPS_PORT=80chdir /home/mindmaps/appexec authbind /home/mindmaps/vert.x-2.0.1-final/bin/vertx run app.js Let's go through the file bit by bit as follows: On the first two lines, we configure when this service will start and stop. This is defined using runlevels, which are numeric identifiers of different states of the operating system (http://en.wikipedia.org/wiki/Runlevel). 2, 3, 4, and 5 designate runlevels where the system is operational; 0, 1, and 6 designate runlevels where the system is stopping or restarting. We set the user and group the service will run as to the mindmaps user and its group. We set the two environment variables we also used earlier when testing the service: JAVA_OPTS for letting Java know it should only use the IPv4 stack, and MINDMAPS_PORT to let our application know that it should use port 80. We change the working directory of the service to where our application resides, using the chdir directive. Finally, we define the command that starts the service. It is the vertx command wrapped in the authbind command. Be sure to change the directory for the vertx binary to match the directory you installed Vert.x to. Let's give the mindmaps user the permission to manage this job so that we won't have to always run it as root. Open up the /etc/sudoers file into an editor with the following command: sudo /usr/sbin/visudo At the end of the file, add the following line: mindmaps ALL = (root) NOPASSWD: /sbin/start mindmaps, /sbin/stopmindmaps, /sbin/restart mindmaps, /sbin/status mindmaps The visudo command is used to configure the privileges of different users to use the sudo command. With the line we added, we enabled the mindmaps user to run a few specific commands without having to supply a password. At this point you should be able to start and stop the application as the mindmaps user: sudo start mindmaps You also have the following additional commands available for managing the service: sudo status mindmapssudo restart mindmapssudo stop mindmaps If there is a problem with the commands, there might be some configuration error. The upstart service will log errors to the file: /var/log/upstart/mindmaps.log. You will need to open it using the sudo command. Deploying new versions Deploying a new version of the application consists of the following two steps: Transferring new files over using rsync Restarting the mind maps service We can make this even easier by creating a shell script that executes both steps. Create a file called deploy.sh in the root directory of the project and set its contents as: #!/bin/shrsync -rtzv . mindmaps@192.168.33.10:~/app/ssh mindmaps@192.168.33.10 sudo restart mindmaps Make the script executable, using the following command: chmod +x deploy.sh After this, just run the following command whenever you want a new version on the server: ./deploy.sh To make deployment even more streamlined, you can set up SSH public key authentication so that you won't need to supply the password of the mindmaps user as you deploy. See https://help.ubuntu.com/community/SSH/OpenSSH/Keys for more information. Summary In this article, we have learned the following things: How to set up a Linux server for Vert.x production deployment How to set up deployment for a Vert.x application using rsync How to start and supervise a Vert.x process using upstart Resources for Article : Further resources on this subject: IRC-style chat with TCP server and event bus [Article] Coding for the Real-time Web [Article] Integrating Storm and Hadoop [Article]
Read more
  • 0
  • 0
  • 6425

article-image-file-information-perforce-crm
Packt
24 Sep 2013
17 min read
Save for later

File Information in Perforce CRM

Packt
24 Sep 2013
17 min read
(For more resources related to this topic, see here.) File properties Every file has properties. Some of these properties relate to how files are represented in your workspace. Some relate to the history of the file. Still others will impact how Perforce can manage that file. While various file properties are exposed in different parts of the P4V interface, the Files tab in the view pane provides you with the maximum amount of detail with the minimum effort. The following screenshot shows a file selected in the tree panel along with the information that would be presented in the Files tab: The Files tab presentation has two primary sections. The upper section presents information for the files in a folder using a tabular format. This provides a useful, easy to use, and comparative presentation. The lower section provides information specific to a single file selected in the upper tabular section. This provides you with the ability to focus on additional details once you've identified files of interest using the tabular upper section. The tabular section presents a selected set of the information available for a file. As you'll see shortly, the information selected is under your control. The Details tab provides all of the available information, and shows in addition the explicit mapping between the Workspace and Depot locations of the file. These locations can be seen in various parts of the P4V interface. The Checked Out By tab provides details about all of the workspaces that have a file checked out. These are the full details. You will see summaries of this information in the tree panel hover tips. The Preview tab shows the contents of text files. This is particularly useful when browsing repository files that are not currently present in your workspace. Customizing the tabular display While the tabular section of the Files tab is useful, without order it is still just a collection of data. P4V allows you to sort on any of the displayed columns. It also allows you to select which columns are displayed to help you focus on important factors. You can reorder the columns by clicking on a column header, dragging it, and dropping it in the position you desire. You can also select the column displayed in the table by right-clicking on the header bar and then checking the columns you want displayed, as shown in the following screenshot: Note the triangle indicator in the Name column header. This specifies that the table entries are sorted based on the value in the Name column. A triangle pointing upwards sorts in ascending order, a triangle pointing downwards sorts in descending order. Sorting on either the Latest Changelist or Date Last Submitted columns allows you to quickly identify more recently or least recently changed files. Explaining the # characters The # character is the Perforce notation indicating the file revision. So foo.txt#3 indicates revision (or version) 3 of the file foo.txt. Using this notation saves a lot of screen space and reduces visual clutter. It's also the versioning notation you'll see in the log panel or which you would use on the command line. But what about things like #5/5, #3/5, #0/5 or even #25 of 25? Not to worry, long division and set theory are not involved. This is simply a notation that indicates the version of the file in your workspace and the maximum number of file versions the server knows about. So #5/5 would indicate that you have version 5 of the file in your workspace and that is the most up-to-date version the server knows about. Likewise, #3/5 would indicate that you have version 3 of the file in your workspace, yet the server knows about two more recent versions: 4 and 5. While #0/5 indicates that you have no version of the file in your workspace. Finally, the #25 of 25 notation has replaced the "/" with "of" to increase readability. 0 is the workspace version of deleted files and files marked for add, but not yet submitted. Showing deleted files The deleted files are visible in the depot tree only if you turn on the filter to show them, as we see in the following screenshot: The filter Show Deleted Depot Files has been checked. As a result, we can see a file execmac.cwhere the latest revision is 2, and the tooltip (as well as the icon) shows us that it is deleted at head revision. As we will discuss later in this article, the head revision is the latest revision in the repository. This filter is not available if you have selected the Workspace tab since deleted files do not exist locally. Type and filetype P4V understands two separate type concepts relating to files. Knowing the difference and how they apply will come in handy. One concept is known as type and refers to an association based on the file name extension. This is managed by the operating system on the local workstation. For example, Windows might associate the .docx extension with the Microsoft Word application. The server maintains no information about type. By default, this relationship is used by P4V to select the tool to use when it opens a file for you. For example, if you ask P4V to open a file called foo.html and you have a web development tool installed, it may launch that tool. If you don't have such a tool, then it might launch a browser. Not to worry, you can override this behavior. The other concept is known as filetype, and refers to the information Perforce uses to define workspace population characteristic, control P4V processing, and define server storage parameters. The server maintains filetype information on a per-revision basis. When a file is first added it is assigned a filetype. That filetype persists until it is explicitly changed. Most of the time, you will not need to worry about specifying a particular filetype. P4V uses several techniques to assure that the appropriate filetype is established when a file is first added (including defaults configured by your administrator). Of course you can always explicitly specify a filetype, but that is for advanced users. The two basic filetypes are text and binary. Perforce knows that text files have line endings. When it populates your workspace with a text file it automatically adapts the line endings within the file to the encoding appropriate for your operating system. It is also understood that text files can be compared in ways that humans can understand. On the other hand, binary files are treated as a collection of bytes. They receive no special processing when populating your workspace, and it is understood that they can't usually be compared in ways that humans would understand. Filetype can also specify other attributes of files, such as making files always writable in workspaces. They can also set the executable bit on Linux/Unix for shell scripts or executable binaries. Understanding file versions and history In this article, we are going to first look at how to get older revisions of files into our workspace and how to understand the history of a file or a set of files. That includes understanding how file revisions relate to changelists, and the state of the repository as of a particular date and time. We often need to have a look at older versions of files. When looking at a project, you may need to reproduce an older release, or understand a particular baseline which is a set of files or a complete folder or tree. Getting different revisions of files On the right-click menu for a file or folder there is a Get Revision…option, as shown in the following screenshot: Clicking on the preceding option brings up the following dialog: Various actions are possible with this dialog. For now, we will focus on choosing between Get latest revision and Specify revision using:. Get latest revision updates the workspace files with the highest revision of the files known to the server. This is also known as getting or syncing to the head revision. The head version is a special version with its own reference #head. You will see #head in the log pane and in various error and status reports. Specify revision using: updates the workspace files with either explicit revisions or revisions that are implied from a context such as date/time, label, or changelist. Don't worry that you don't know what all of the Specify revision using: choices are or what they do. Take a moment to scan through the choices. Note the Browse… results. They are designed to reduce typing errors to get you the specific revision you're interested in. How file revisions relate to changelists The following screenshot shows the history of fileos2.c using the Revision Graph tool, which is available on the right-click menu for the currently selected file within the tree pane (right-click, then select Revision Graph). Note that for clarity we have turned off various panes within the tool to show the minimum necessary, and included the Legend option to explain the shapes: This shows us the association between revisions of a file and the changelists in which those revisions were submitted to the repository. In this example, revision 3 was part of changelist 294, and revision 2 was part of changelist 279. The file was first created and thus added to the repository as revision 1 in changelist 220. It is fairly clear that a Get latest would give us revision 3 of the file in our workspace. Similarly, if we Specify revision using: changelist 279 we would get revision 2 of the file. So what would you expect if we chose changelist 280? Doing a get which specifies a changelist gives us the state of the repository at the point of that changelist. In this case, it will give us revision 2. Revision 2 is the latest revision up to or including the specified changelist. In fact for this file, getting any changelist between 279 and 293 inclusive, will give us revision 2. What would we expect if you do a get which specifies changelist 100? The preceding history shows us that this file did not exist in the repository as of that changelist. Therefore, a get of that changelist would remove the file from our workspace because it didn't exist as of that changelist. Using Perforce terminology, we would have revision 0, or the revision which does not exist, in our workspace. Removing version 0 files from a workspace is designed to avoid the inevitable user errors that would occur if you had to delete the file yourself. Potentially surprising get revision results! Following on from the preceding examples, what would you expect if you tried to get changelist 9999999 or some equally large number, for which a changelist doesn't yet exist? Hopefully, it is not a big surprise that we just get the latest revision of the file. In the preceding case, revision 3. As we saw previously, even though the changelist doesn't directly contain this file, the file still associates revisions with every changelist, even those that don't yet exist. This large changelist technique is actually just an obscure version of get latest. Obscure is not usually a good engineering practice. But watch out! What will happen if we try to get revision 5 of this file? For this file, revision 5 does not exist. Therefore the get request treats this as if you requested revision 0 so it will remove the file from the workspace. Be very careful getting more than one file as of a specific version number. When more than one file is involved, this gets that version of every file that has that many versions or more and removes (#0) the rest. This is usually not what you want. Changelists and folders People don't always realize that the Revision Graph… right-click option can also apply to folders. The folder view shows all of the files at one time, as seen in the following screenshot: In the preceding screenshot, the cursor is hovering over changelist 370, and the 3 files in the folder that had new versions created by that changelist are highlighted. What would we get if we synced the entire folder to changelist 370? By default, we would get the files in that particular changelist and the version for every other file in the folder as of that changelist. In the preceding screenshot that would be version 3 of Jamfile.html, which was submitted in changelist 369. But, index.html at version 0 would be removed from the workspace because it didn't exist until changelist 383. Therefore, we can see that a changelist can be used in two ways: To refer to the set of files submitted in that changelist To refer to the state of the entire repository (or any part of it such as a folder), up to and including that changelist When waxing philosophical, we sometimes refer to this as the particle nature versus the wave nature of changelists! Get revision options We haven't yet covered the options in the Get Revision… dialog shown in the following screenshot. They provide functionality that can be difficult to achieve using other techniques. The preceding screenshot shows the output on clicking Preview. We see what the results would be, without actually affecting anything in our workspace. This can help avoid surprises and perhaps prevent unnecessary mistakes. The Force Operation (replace file even if you already have the revision specified)checkbox, if checked, will update the files in our workspace to the specified revisions, even if P4V thinks we already have those revisions. You need to force operations when files have been removed from the workspace without coordinating that removal with Perforce. Following on from the discussion in the previous section about a Get Revision, always getting files up to or including the changelist, we can modify this behavior by checking Only get revisions for files listed in changelist. With this option you update your workspace with only the file versions created by that changelist. If the following changelist is discovered to cause a problem, then it can be very useful to get a workspace into the state immediately before that changelist. Referencing a specific date and/or time The Get Revision dialog allows us to specify a date and time, as shown in the following screenshot: Every submitted changelist has an associated date and time of submission. The value specified in this dialog will give the same results as if you were to do a get specifying the changelist that was submitted precisely at or most closely before the specified date and time. Most people prefer to reference using changelist numbers rather than date and time. Changelists are unique and unambiguous. More than one changelist may be submitted within the one second granularity of date and time tracking. And communicating date and time across time zones is error prone at best. Referencing a label As stated in the preceding section, we can also do a get relative to a particular label: You can type the name of the label in directly. However, most people prefer to select an appropriate label from the choices presented when you click on the Browse…button. Most Perforce users don't use labels. They use changelists. Files in another workspace You can also reference file versions in another workspace: As previously stated, we can type the workspace name in the field or browse to select a workspace. This feature is most useful when you're trying to resolve scenarios where it works/ fails in my workspace. Most people use it with Preview so that they don't impact their current workspace. However, it does require that both workspaces reference the same depot files. This is only likely to be true for continuous build and code review environments. Depot paths The path of currently selected files or folders is shown in the address bar at the top of the screen, as per the following screenshot: You can turn off the address bar by right-clicking on it and unchecking the option. There is also a shortcut key (Ctrl + C) which copies the full path of the currently selected file or folder to the clipboard. This can be useful for documentation purposes. Depending on whether you have the depot or workspace tab showing, you might get: //depot/Jam/MAIN/src/Build.com Or, depending on your workspace definition: c:workbruno_mainJamMAINsrcBuild.com Finding files – an introduction to wildcards It is easy to find files with certain characters in their names by going to the Search | Find File… menu option. This will give you the Find File tab, as shown in the following screenshot: In the preceding screenshot, we had a particular folder selected, and that is copied to the Search in: field. Sharp eyed readers will have noticed that the full path contains some extra characters: //depot/Jam/MAIN/.... In this instance, P4V has added the ... wildcard to the directory path (this wildcard is also known as an ellipsis). This wildcard means that all subfolders should be included in the search. We will look at more wildcard options in the next section of this article. You can also drag-and-drop directory paths from the tree pane on the left-hand side to the Search in field and the contents will be appropriately updated. If we enter, for example, unix into the Names matches any of the following field and click on Find, we might get results as shown in the following screenshot: In this particular example, we can see that there are three files in that folder (or in any subfolders) containing unix in their filename. By default, the results do not include any files where the latest revision is marked as deleted. You can change this by checking Include deleted depot files. Note that it is possible to filter the results further using the Submission date or changelist option:, for example: When working with dates you can search for particular periods of time, as seen here: We invite you to explore this powerful feature on your own! Showing history The history of both files and folders can be seen via the History tab. You can go to the View | History menu option or click on the appropriate toolbar icon. This tab can show the history for the currently selected file or folder in the tree pane. You can right-click on a file in the tree pane and select File History. If you have a folder selected the menu option is Folder History. File history The history for a file might be: In this example, we can see the basic history information for the selected file. For each revision we see information such as Changelist and Date Submitted. As previously seen with the File Properties tab, by right-clicking the column headers you can select other columns to be displayed. When this tab is displayed, clicking to select another file in the tree pane will cause the tab to be updated dynamically. The icon for revision 8 in the preceding screenshot has a highlight around it, this shows that this revision is the one currently present in the workspace. The History tab also has a details tab which can be shown if you wish, by dragging the splitter bar upwards with the mouse, as shown here: Folder history For a folder, the History tab shows all changelists that have affected files in that folder or any of its subfolders. This acts in the same way for a depot. An example is shown here: Notice that there is no column for revisions as they only apply to files, not to folders. If you drag-and-drop a column header onto another one (left or right), you can change the order they are displayed in.
Read more
  • 0
  • 0
  • 3547

Packt
24 Sep 2013
8 min read
Save for later

Quick start – using Haml

Packt
24 Sep 2013
8 min read
(For more resources related to this topic, see here.) Step 1 – integrating with Rails and creating a simple view file Let's create a simple rails application and change one of the view files to Haml from ERB: Create a new rails application named blog: rails new blog Add the Haml gem to this application's Gemfile and run it: bundle install When the gem has been added, generate some views that we can convert to Haml and learn about its basic features. Run the Rails scaffold generator to create a scffold named post. rails g scaffold post After this, you need to run the migrations to create the database tables: rake db:migrate You should get an output as shown in the following screenshot: Our application is not yet generating Haml views automatically. We will switch it to this mode in the next steps. The index.html.erb file that has been generated and is located in app/views/posts/index.html.erb looks as follows: <h1>Listing posts</h1><table> <tr> <th></th> <th></th> <th></th> </tr><% @posts.each do |post| %> <tr> <td><%= link_to 'Show', post %></td> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm:'Are you sure?' } %></td> </tr><% end %></table><br><%= link_to 'New Post', new_post_path %>] Let's convert it to an Haml view step-by-step. First, let's understand the basic features of Haml: Any HTML tags are written with a percent sign and then the name of the tag Whitespace (tabs) is being used to create nested tags Any part of an Haml line that is not interpreted as something else is taken to be plain text Closing tags as well as end statements are omitted for Ruby blocks Knowing the previous features we can write the first lines of our example view in Haml. Open the index.html.erb file in an editor and replace <h1>, <table>, <th>, and <tr> as follows: <h1>Listing posts</h1> can be written as %h1 Listing posts <table> can be written as %table <tr> becomes %tr <th> becomes %th After those first replacements our view file should look like: %h1 Listing posts%table %tr %th %th %th<% @posts.each do |post| %> <tr> <td><%= link_to 'Show', post %></td> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm:'Are you sure?' } %></td> </tr><% end %><br><%= link_to 'New Post', new_post_path %> Please notice how %tr is nested within the %table tag using a tab and also how %th is nested within %tr using a tab. Next, let's convert the Ruby parts of this view. Ruby is evaluated and its output is inserted into the view when using the equals character. In ERB we had to use <%=, whereas in Haml, this is shortened to just a =. The following examples illustrate this: <%= link_to 'Show', post %> becomes = link_to 'Show', post and all the other <%= parts are changed accordingly The equals sign can be used at the end of the tag to insert the Ruby code within that tag Empty (void) tags, such as <br>, are created by adding a forward slash at the end of the tag Please note that you have to leave a space after the equals sign. After the changes are incorporated, our view file will look like %h1 Listing posts %table %tr %th %th %th<% @posts.each do |post| %> %tr %td= link_to 'Show',post %td= link_to 'Edit',edit_post_path(post) %td= link_to 'Destroy',post,method: :delete,data: { confirm: 'Areyou sure?' }%br/= link_to 'New Post',new_post_path The only thing left to do now is to convert the Ruby block part: <% @posts.each do | post | %>. Code that needs to be run, but does not generate any output, is written using a hyphen character. Here is how this conversion works: Ruby blocks do not need to be closed, they end when the indentation decreases HTML tags and the Ruby code that is nested within the block are indented by one tab more than the block <% @posts.each do |post| %> becomes - @ posts.each do |post| Remember about a space after the hyphen character After we replace the remaining part in our view file according to the previous rules, it should look as follows: %h1 Listing posts%table %tr %th %th %th- @posts.each do |post| %tr %td= link_to 'Show', post %td= link_to 'Edit', edit_post_path(post) %td= link_to 'Destroy', post, method: :delete, data: { confirm:'Are you sure?' }%br/= link_to 'New Post', new_post_path Save the view file and change its name to index.html.haml. This is now an Haml-based template. Start our example Rails application and visit http: //localhost:3000/posts to see the view being rendered by Rails, as shown in the following screenshot: Step 2 – switching Rails application to use Haml as the templating engine In the previous step, we have enabled Haml in the test application. However, if you generate new view files using any of the Rails built-in generators, it will still use ERB. Let's switch the application to use Haml as the templating engine. Edit the blog application Gemfile and add a gem named haml-rails to it. You can add it to the :development group because the generators are only used during development and this functionality is not needed in production or test environments. Our application Gemfile now looks as shown in the following code: source 'https://rubygems.org'gem 'rails', '3.2.13'gem 'sqlite3'gem 'haml'gem 'haml-rails', :group => :developmentgroup :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3'endgem 'jquery-rails' Then run following bundle command to install the gem: bundle install Let's say the posts in our application need to have categories. Run the scaffold generator to create some views for categories. This generator will create views using Haml, as shown in the following screenshot: Please note that new views have a .html.haml extension and are using Haml. For example, the _form.html.haml view for the form looks as follows: = form_for @category do |f|Asjd12As - if @category.errors.any? #error_explanation %h2= "#{pluralize(@category.errors.count, "error")} prohibitedthis category from being saved:" %ul - @category.errors.full_messages.each do |msg| %li= msg .actions = f.submit 'Save' There are two very useful shorthand notations for creating a <div> tag with a class or a <div> tag with an ID. To create a div with an ID, use the hash symbol followed by the name of the ID. For example, #error_explanation will result in <div id="error_explanation"> To create a <div>tag with a class attribute, use a dot followed by the name of the class. For example, .actions will create <div class="actions"> Step 3 – converting existing view templates to Haml Our example blog app still has some leftover templates which are using ERB as well as an application.html.erb layout file. We would like to convert those to Haml. There is no need to do it all individually, because there is a handy gem which will automatically convert all the ERB files to Haml, shown as follows: Let's install the html2haml gem: gem install html2haml Using the cd command, change the current working directory to the app directory of our example application and run the following bash command to convert all the ERB files to Haml (to run this command you need a bash shell. On Windows, you can use the embedded bash shell which ships with GitHub for Windows, Cygwin bash, MinGW bash, or the MSYS bash shell which is bundled with Git for Windows). for file in $(find . -type f -name \*.html.erb); do html2haml -e ${file} "$(dirname ${file})/$(basename ${file}.erb).haml";done Then to remove the ERB files and run this command: find ./ -name *erb | while read line; do rm $line; done Those two Bash snippets will first convert all the ERB files recursively in the app directory of our application and then remove the remaining ERB view templates. Summary This article covered integrating with Rails and creating a simple view file, switching Rails application to use Haml as the templating engine, and converting existing view templates to Haml. Resources for Article : Further resources on this subject: Building HTML5 Pages from Scratch [Article] URL Shorteners – Designing the TinyURL Clone with Ruby [Article] Building tiny Web-applications in Ruby using Sinatra [Article]
Read more
  • 0
  • 0
  • 14585
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

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
Modal Close icon
Modal Close icon