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

How-To Tutorials

7019 Articles
article-image-useful-maven-plugins-part-2
Packt
09 Nov 2009
12 min read
Save for later

Useful Maven Plugins: Part 2

Packt
09 Nov 2009
12 min read
The Build Helper plugin Within Maven, there are a number of common tasks which plugins can perform to alter the current project for changes occurring during the build. We have seen the inclusion of new resources in the Remote Resources plugin, and the attachment of a new artifact from the Shade plugin. It is also possible to have a plugin generate new source code and include it for compilation, even though the directory is not included in the POM file. The role of the Build Helper plugin is to provide a set of goals that can help achieve a collection of small but common tasks for which it would not be worth writing a custom plugin. Adding source directories Maven's inability to have multiple source directories in the project model has often been called into question. However, as time has progressed the request has died down as the idea of a standardized source structure took hold. The Build Helper plugin offers the ability to add another source directory or test source directory to that configured in the POM. This is not necessarily to allow a workaround for the deliberate limitation in the project model, but rather to facilitate other use cases that require it. The most common need to use this technique is to assist with the migration of a project in an existing layout to Maven temporarily. Even with this capability it is still recommended not to add multiple source directories without a particular reason—apart from breaking with convention, you may find that some tools that operate based on the values in the POM will not recognize the additional directories as containing source code. The following example illustrates the addition of a source directory: <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>src/main/more-java</source> </sources> </configuration> </execution> </executions></plugin> The need to use the Build Helper plugin for adding sources is now becoming more rare. Maven plugins that generate source code would be likely to add the extra directory to the project internally without the need for additional configuration. If some other means is used to generate the sources—for example, from a scripting plugin—it is common for the scripting plugin to have a way to add the source directory with fewer configurations than using the Build Helper plugin. However, if the need does arise, the Build Helper plugin will prove itself useful. Attaching arbitrary artifacts A similar scenario that can occur is the generation of additional artifacts that need to be attached to the build process. This means they use the same POM to define them, but are different types of related build artifacts, with their own classifier. The artifacts are installed and deployed to the repository alongside the original. Typically, this will be in the form of another JAR file, possibly generated by one of the scripting plugins that did not attach the artifact itself. However, it could be used for any number of files that need to be stored in the repository alongside the main artifact. Consider the example of deploying the license to the repository—if you were to run the install phase on the given project, you would be able to have the license installed into the local repository alongside the main artifact and its POM. In reality, this particular configuration may be overkill, especially if the licenses are identical across many projects, or can be derived from the POM. However, depending on your deployment needs this possibility can be helpful in ensuring the repository contains the information about an artifact that you need, at the time it was deployed, in addition to any extra build artifacts that might be generated. In our example application, we generated the license in two places—in all the Java modules, and the final distribution. Deploying it along with the final distribution makes some sense, so let's add it to the distribution/pom.xml file: <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.1</version> <configuration> <artifacts> <artifact> <file> target/maven-shared-archive-resources/LICENSE </file> <type>txt</type> <classifier>license</classifier> </artifact> </artifacts> </configuration> <executions> <execution> <goals> <goal>attach-artifact</goal> </goals> </execution> </executions></plugin> This goal will execute after the packaging has occurred, but before installation so that it can be attached to the installation (and deployment) process. The file to attach is the license generated earlier by the Remote Resources plugin and is given an extension of .txt and classifier of -license. When running the install phase, we now see the file being processed: [INFO] [build-helper:attach-artifact {execution: default}][INFO] [enforcer:enforce {execution: default}][INFO] [install:install][INFO] Installing /Users/brett/code/06/centrepoint/distribution/target/pom-transformed.xml to /Users/brett/.m2/repository/com/effectivemaven/centrepoint/distribution/1.0-SNAPSHOT/distribution-1.0-SNAPSHOT.pom[INFO] Installing /Users/brett/code/06/centrepoint/distribution/target/centrepoint-1.0-SNAPSHOT-bin.zip to /Users/brett/.m2/repository/com/effectivemaven/centrepoint/distribution/1.0-SNAPSHOT/distribution-1.0-SNAPSHOT-bin.zip[INFO] Installing /Users/brett/code/06/centrepoint/distribution/target/centrepoint-1.0-SNAPSHOT-bin.tar.gz to /Users/brett/.m2/repository/com/effectivemaven/centrepoint/distribution/1.0-SNAPSHOT/distribution-1.0-SNAPSHOT-bin.tar.gz[INFO] Installing /Users/brett/code/06/centrepoint/distribution/target/maven-shared-archive-resources/LICENSE to /Users/brett/.m2/repository/com/effectivemaven/centrepoint/distribution/1.0-SNAPSHOT/distribution-1.0-SNAPSHOT-license.txt Other goals The Build Helper plugin also contains some other goals in the latest release at the time of writing (v1.1) of more specific interest: remove-project-artifact: To clean the local repository of artifacts from the project being built to preserve space and remove outdated files. This may occur if the build no longer produces those files, or if it is necessary to remove older versions. reserve-network-port: Many networked applications may want to use a network port that doesn't conflict with other test cases. This goal can help reserve unique ports to use in the tests. This is useful for starting servers in integration tests and then referencing them in the test cases. However, note that it won't be available when running such tests in a non-Maven environment such as the IDE. The goals available in the Build Helper plugin may increase over time, so if you have some small, common adjustments to make it is a good place to look to first for those utilities. The AntRun plugin and scripting languages Maven was designed to be extended through plugins. Because of the fact that this is so strongly encouraged, there are now many plugins available for a variety of tasks, and the need to write your own customizations, particularly for common tasks, is reduced. However, no two projects are the same, and in some projects, there are likely to be some customizations that will need to be made that are not covered by an existing plugin. While it is virtuous to write a plugin for such cases so that it can be reused in multiple projects, it is also very reasonable to use some form of scripting for short, one off customizations. One simple option is to use the AntRun plugin. Ant still contains the largest available set of build tasks to cover the types of customizations that you might need in your build, and through this plugin you can quickly string together some of these tasks within the Maven life cycle to achieve the outcome that you need. Running simple tasks We have already used the AntRun plugin in the distribution module of the example application. This snippet was used to copy some configuration files into place and create a logs directory, ready for the Assembly plugin to create the archive from: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>config</id> <phase>process-resources</phase> <configuration> <tasks> <copy todir="${project.build.directory}/generated- resources/appassembler/jsw/centrepoint/conf"> <fileset dir="src/main/conf" /> </copy> <mkdir dir="${project.build.directory}/generated- resources/appassembler/jsw/centrepoint/logs" /> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions></plugin> This shows how quick and useful the AntRun plugin can be for simple tasks. However, it also contains a number of other features that can be of benefit to the build for more significant tasks. Interacting with the Maven project As we mentioned in the section, The Build Helper plugin, you can tell the plugin to map some directories to new source directories. This functionality is identical to that of the Build Helper plugin, but is more conveniently located when the directories are being generated by Ant tasks. This can be useful because even though tools are increasingly supplying native Maven plugins in addition to Ant tasks, you might come across a source generation tool that only has an Ant task. In this scenario, you can use the AntRun plugin to run the tool, generate the source code, and use the sourceRoot parameter to have that directory added back into the build life cycle. In addition to injecting source directories back into the life cycle, the AntRun plugin also injects Maven project information into Ant's context. Probably the most important of these is the availability of the project's and plugin's dependencies as Ant path references: maven.compile.classpath: The dependencies in the compile scope (this syntax will look familiar to those that used Maven 1's built in Ant-based files) maven.runtime.classpath: The dependencies in the runtime scope (including the above) maven.test.classpath: The dependencies in the test scope (including both of the above) maven.plugin.classpath: The dependencies of the AntRun plugin itself, including any added via the POM Though we have not needed it in the example application, to illustrate how these two options would work, consider if you needed to use the XJC Ant task from JAXB to generate some sources. JAXB is a Java-to-XML binding framework that can be used to generate Java source code from XML schema (among many other things), using its XJC tool. Though it serves as a suitable example here, you would not be faced with this issue with JAXB itself, as it now offers a Maven plugin. In this example, you might add the following configuration to an AntRun execution in a POM file: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> <executions> <execution> <id>xjc</id> <phase>generate-sources</phase> <configuration> <tasks> <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask" classpathref="maven.plugin.classpath" /> <xjc destdir="${project.build.directory}/xjc" schema="src/main/jaxb/schema.xsd"> <classpath refid="maven.compile.classpath" /> </xjc> </tasks> <sourceRoot>${project.build.directory}/xjc</sourceRoot> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>2.1.9</version> </dependency> </dependencies></plugin> We see here that the XJC Task is defined using the plugin classpath to locate the task and its dependencies (and that task's artifact is added as a plugin dependency to accommodate this). Additional built-in Ant tasks would also be added as plugin dependencies (such as ant-nodeps). AntRun and Ant versions While in some cases they might be compatible, generally you should use the same version of the Ant optional tasks as the version of Ant itself. The version of Ant used by the plugin is predetermined by what it has been built against. In AntRun v1.3, that is Ant 1.7.1. To use a different version of Ant, consider a different version of the AntRun plugin. Next, the task is run—being passed the project's dependencies and schema to generate the source code from. The source code is output to target/xjc, which is also added as a source directory by the AntRun plugin because of the configuration specified. As the task runs in the generate-sources phase, it is available for compilation in the same way as any other source code. Again, the configuration of AntRun here has been relatively simple, and is completely integrated with the Maven artifact handling and build life cycle such that it would not likely be needed to write a plugin to wrap the tool completely if you were faced with this decision in your environment.
Read more
  • 0
  • 0
  • 7273

article-image-useful-maven-plugins-part-1
Packt
09 Nov 2009
13 min read
Save for later

Useful Maven Plugins: Part 1

Packt
09 Nov 2009
13 min read
Nobody can tell exactly how many Maven plugins exist today—since, like dependencies they can be retrieved from any specified remote repository, there are likely hundreds to choose from, and likely even more that have been custom written for use within the infrastructure of particular organizations. A common practice for frameworks and tools that require build integration is to publish a Maven plugin to accomplish the task—and it is becoming increasingly common to encounter this as a standard part of the getting started section of a project you might hope to use. However, there are also a number of plugins that would be considered general purpose and handle some extended build cases in a wider variety of projects. While this won't come close to covering all the plugins you are likely to encounter, with these common tools in your arsenal it will cover many of your Maven build needs, reducing the need for you to write your own plugins. The Remote Resources plugin Most projects will use the Resources plugin at some point, even if it isn't configured directly—it is standard in the default life cycle for any packaging that produces some type of artifact, bundling the resources found in src/main/resources. However, what if you wanted to share those resources among multiple projects? The best approach to doing that is to store the resources in the repository and retrieve them for use in multiple builds—and that is where the Remote Resources plugin comes in. First, we should note that this is not the only alternative for handling the scenario. The Dependency plugin's unpack goal is also quite capable of unpacking an artifact full of resources directly into the location that will be packaged. However, the Remote Resources plugin offers several advantages: Re-integration with the resources life cycle so that retrieved resources will automatically be processed in any goals in the process-resources phase. The ability to perform additional processing on the resources (including the optional use of Velocity templates to generate the resources) before inclusion. A specific bundle generation goal for creating the resource artifact in the first place. These advantages can make the plugin very effective at dealing with some common scenarios. For example the inspiration for the creation of the plugin, and one of its more common uses, is to place aggregated license files within the final artifact. There are other scenarios where the dependency:unpack goal remains more suitable. It is best to select the Remote Resources plugin when the files will be incorporated into the resources life cycle and the Dependency plugin when the files will be utilized independently. Let's look at how to create a license file for our Centrepoint application. We will do this in two steps—the creation of the resource bundle that provides the generic resources for any project by the same organization, and the processing of the module resources. Creating a Remote Resource bundle Remote Resource bundles are regular JAR files packaged with additional information generated by the remote resource plugin's bundle goal. Creating a module follows the same process as with other JAR files. In the example application, we will create the module outside of the Centrepoint multi-module hierarchy, so that it could (theoretically) be used by other projects from the same organization. This could be anywhere in source control, but we will assume it sits side-by-side with the effectivemaven-parent module in the workspace. $ mvn archetype:generate -DartifactId=license-resources -DgroupId=com.effectivemaven As this is not going to be a code project, the src/main/java and src/test directories can be removed from the generated content. We then continue to add the parent project to the POM, so the result looks like the following: <project xsi_schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.effectivemaven</groupId> <artifactId>effectivemaven-parent</artifactId> <version>1-SNAPSHOT</version> <relativePath>../effectivemaven-parent/pom.xml</relativePath> </parent> <artifactId>license-resources</artifactId> <version>1.0-SNAPSHOT</version> <name>License Resource Bundle</name> </project> We will add the Remote Resources plugin shortly, but first let's create the resources that will be bundled. These are added to the src/main/resources like regular resources. Consider the following Velocity template file, src/main/resources/LICENSE.vm: ## License Generator #macro(showUrl $url) #if($url) ($url) #end #end This software is distributed under the following license(s): #foreach ($l in $project.licenses) - $l.name #showUrl ($l.url) #end #if (!$projectsSortedByOrganization.isEmpty()) The software relies on a number of dependencies. The individual licenses are outlined below. #set ($keys = $projectsSortedByOrganization.keySet()) #foreach ($o in $keys) From: '$o.name' #showUrl($o.url) #set ($projects = $projectsSortedByOrganization.get($o)) #foreach ($p in $projects) - $p.name #showUrl ($p.url) $p.artifact #foreach ($l in $p.licenses) License: $l.name #showUrl ($l.url) #end #end #end #end For those not familiar with Velocity, the purpose of this is to first iterate through the project's licenses and list them, then secondly iterate through the project's dependencies (grouped by the organization they are from) and list their license. The $projectsSortedByOrganization variable is a special one added by the Remote Resources plugin to assist in this task. Before we can move on to use the bundle, we need to add the plugin to the bundle project like so: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-remote-resources-plugin</artifactId> <version>1.0</version> <executions> <execution> <goals> <goal>bundle</goal> </goals> </execution> </executions> </plugin> </plugins> </build> This goal is required to generate a bundle manifest, the contents of which tell the plugin which resources to process when it is later called on to do so. With this all in place, we can now install the bundle into the local repository, ready for use: license-resources$ mvn install If you were to inspect the contents of the generated JAR file, you would see both the LICENSE.vm file in the root, and the bundle manifest in META-INF/maven/remoteresources.xml. You would also find that the Velocity template is unmodified—the contents will be executed when the bundle is later processed in the target project, which we will proceed to look at now. Processing Remote Resources in a project Using the resource bundle we have created is now quite straightforward. We start by adding the folllowing to the build section of modules/pom.xml file of Centrepoint: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-remote-resources-plugin</artifactId> <version>1.0</version> <executions> <execution> <goals> <goal>process</goal> </goals> </execution> </executions> <configuration> <resourceBundles> <resourceBundle> com.effectivemaven:license-resources:1.0-SNAPSHOT </resourceBundle> </resourceBundles> </configuration> </plugin>   Here we have added a list of resource bundle artifacts to the configuration for the process goal, in the familiar shorthand artifact notation of groupId:artifactId:version. It has been added to the modules POM so that the license is included in the JAR files, but not included in the other non-code modules such as the documentation (which already generates a copy of the license from the reporting plugins). Normally, you should use a released version of the license bundle, not a snapshot as we have here (as we have not yet covered the release process!). Since the bundle is configured directly and not through a dependency, the Release plugin will not detect this unresolved snapshot later. Now, if we build a module such as store-api, we will see the license included in the root directory of the JAR file with the following content: This software is distributed under the following license(s): - The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) The software relies on a number of dependencies. The individual licenses are outlined below. From: 'Apache Maven 2: Effective Implementations Book' (http://www.effectivemaven.com/) - Centrepoint Data Model com.effectivemaven.centrepoint:model:jar:1.0-SNAPSHOT License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) From: 'Google' (http://www.google.com/) - Guice (http://code.google.com/p/google-guice/) com.google.code.guice:guice:pom:1.0 License: The Apache Software License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt) This is a good start, but we don't really need to include our own artifacts in the list, so we go back to the plugin declaration in modules/pom.xml and add another line of configuration: <configuration> <excludeGroupIds>${project.groupId}</excludeGroupIds> <resourceBundles> ... Regenerating the above artifact will alter the license to remove the dependencies from the project's group. A different case is the final distribution. As this is not part of the modules hierarchy, first we need to include the plugin definition identical to the one added previously. In the sample code for this article, you will notice that this has been taken a step further with the version and common configuration pushed into a pluginManagement section of the Centrepoint parent POM, and just the execution of the plugin goal remains in the modules and distribution POM files. We can now build the assembly as usual: distribution$ mvn clean install Upon inspecting the generated assemblies, you will not see the license file included yet. This is because the Assembly plugin does not pick up Maven resources by default, as it does not participate in the normal life cycle. To include the license file, we must alter the assembly descriptor distribution/src/main/assembly/bin.xml and add the following file set: <fileSet> <directory>target/maven-shared-archive-resources</directory> <outputDirectory>/</outputDirectory> </fileSet> The directory given is the standard location in which the Remote Resources plugin stores the resources it has processed, so if you decide to configure that differently in your own projects you would need to change this to the corresponding location. Upon building the assembly again we will see that the license has been generated, and that it includes the licenses of dependencies outside of the Centepoint application. As you can see, the distributed application depends on Jetty (also under the Apache License 2.0), which includes some portions of Glassfish (under the CDDL 1.0 License). While the above technique can be very helpful in constructing some useful information about your project and its dependencies, it cannot be guaranteed to produce complete licensing information for a project. The method relies on accurate information in the POMs of your dependencies, and this can sometimes be inaccurate (particularly when using public repositories such as the Maven Central Repository). If you are redistributing your files, always confirm that you have correctly recorded any necessary licensing information that must accompany them! The Remote Resources plugin is also capable of covering other scenarios that are particularly suited to license handling or more generally recording information about the project it is being processed for. These include: The supplementalDataModels configuration option that allows you to fill in incomplete or incorrect metadata for a project dependency before the resources are processed (to avoid particular problems as described above). The appendedResourcesDirectory, which allows you to store the above models in a separate file. The properties configuration, which allows the injection of other build properties into the Velocity templates. However, with this in mind, remember that the Remote Resources plugin is often just as suitable for any type of reusable resource, even if it is a static file. The Build Number plugin In Maven Mojos, the goals within a plugin are always designed to be simple tasks. Their aim is to do one thing, and do it well. A good example of this is the Build Number plugin. This simple plugin has one goal (create), with one purpose—to obtain a suitable build number and expose it to the build through properties or a file. While the plugin focuses on exposing the current Subversion revision, it is capable of generating an incremented build number (stored in a specified properties file), and a representation of the current system date and time. This feature can be very useful in identifying the exact heritage of a particular build. The build number generated by the plugin is different to that used by Maven to identify snapshots or artifact versions. While it is possible that you might mark your version using the information it generates, this plugin is typically used to record information about a particular build—whether it is a snapshot, or a release—within the artifact itself as a permanent record. Using the plugin is straightforward. By adding the goal to the project, the Subversion revision and a timestamp property will be exposed from the point that it is run onwards. <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> <version>1.0-beta-1</version> <executions> <execution> <phase>generate-resources</phase> <goals> <goal>create</goal> </goals> </execution> </executions> </plugin> In this example, we execute the plugin in the generate-resources phase so that the properties are available to any resource processing. Note that the values could be used with the Remote Resources plugin that we have just seen. There are two things to take into consideration with this configuration, however. Firstly, not all source builds will be Subversion checkouts, but the plugin does not verify that. To work around this potential problem, you can put the goal into a profile: <profile> <id>buildnumber</id> <activation> <file> <exists>.svn</exists> </file> </activation> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> ... This particular activation check will cause the profile to be used within a Subversion checkout (that is, if .svn exists in the current directory), and to skip the plugin if not. In this case, the properties will not be set (or the file will not be created), so the code using these must take that into account. Secondly, how the values will be accessed needs to be given careful consideration. For example, it is unlikely that you want to create a convoluted build processing step to filter the value into a particular JSP file to appear in a web application. For the sake of keeping the build simple (and speedy), it is best to write the values into a single file that the application can then load from its classpath. This can be achieved by creating a filtered resource that contains references to the values. The advantage of this method is that it is automatic if you have already configured filtered resources, and automatically ends up in the classpath of the application code that can load the file as a resource.
Read more
  • 0
  • 0
  • 6649

article-image-including-charts-and-graphics-pentaho-reports-part-1
Packt
09 Nov 2009
8 min read
Save for later

Including Charts and Graphics in Pentaho Reports (Part 1)

Packt
09 Nov 2009
8 min read
Supported charts Pentaho Reporting relies on JFreeChart, an open source Java chart library, for charting visualization within reports. From within Report Designer, many chart types are supported. In the chart editor, two areas of properties appear when editing a chart. The first area of properties is related to chart rendering, and the second tabbed area of properties is related to the data that populates a chart. Following is the screenshot of the chart editor within Pentaho Report Designer: All chart types receive their data from three general types of datasets. The first type is known as a Category Dataset , where the dataset series and values are grouped by categories. A series is like a sub-group. If the exact category and series appear, the chart will sum the values into a single result. The following table is a simple example of a category dataset: Category Series Sale Price Store 1 Sales Cash $14 Store 1 Sales Credit $12 Store 2 Sales Cash $100 Store 2 Sales Credit $120 Pentaho Reporting builds a Category Dataset using the CategorySetDataCollector. Also available is the PivotCategorySetCollector, which pivots the category and series data. Collector classes implement Pentaho Reporting’s Function API. The second type of dataset is known as an XY Series Dataset, which is a two dimensional group of values that may be plotted in various forms. In this dataset, the series may be used to draw different lines, and so on. Here is a simple example of an XY series dataset : Series Cost of Goods (X) Sale Price (Y) Cash 10 14 Credit 11 12 Cash 92 100 Credit 105 120 Note that X is often referred to as the domain, and Y is referred to as the range. Pentaho Reporting builds an XY Series Dataset using the XYSeriesCollector. The XYZSeriesCollector also exists for three dimensional data. The third type of dataset is known as a Time Series Dataset , which is a two dimensional group of values that are plotted based on a time and date. The Time Series Dataset is more like an XY Series than a Category Dataset, as the time scale is displayed in a linear fashion with appropriate distances between the different time references. Time Series Sale Price May 05, 2009 11:05pm Cash $14 June 07, 2009 12:42pm Credit $12 June 14, 2009 4:20pm Cash $100 June 01, 2009 1:22pm Credit $120 Pentaho Reporting builds a Time Series Dataset using the TimeSeriesCollector. Common chart rendering properties Most charts share a common set of properties. The following properties are common across most charts. Any exceptions are mentioned as part of the specific chart type. Required Property Group Property name Description name The name of the chart object within the report. This is not displayed during rendering, but must be unique in the report. A default name is generated for each chart added to the report. data-source The dataset name for the chart, which is automatically populated with the name of the dataset in the Primary DataSource panel of the chart editor. no-data-message The message to display if no data is available to render the chart. Title Property Group Property name Description chart-title The title of the chart, which is rendered in the report. chart-title-field A field representing the chart title. title-font The chart title's font family, size, and style. Options Property Group Property name Description horizontal If set to True, the chart's X and Y axis are rotated horizontally. The default value is set to False. series-colors The color in which to render each series. The default for the first three series colors are red, blue, and green. General Property Group Property name Description 3-D If set to True, renders the chart in a 3D perspective. The default value is set to False. anti-alias If set to True, renders chart fonts as anti-aliased. The default value is set to True. bg-color Sets the background around the chart to the specified color. If not set, defaults to gray. bg-image Sets the background of the chart area to the specified image. If not set, the background of the chart area defaults to white. The chart area is the area within the axes of the chart. Supported image types include PNG, JPG, and GIF file formats. show-border If set to True, displays a border around the chart. The default value is set to True. border-color Sets the border to the specified color. If not set, defaults to black. plot-border If set to False, clears the default rendering value of the chart border. plot-bg-color Sets the plot background color to the specified color. If not set, defaults to white. plot-fg-alpha Sets the alpha value of the plot foreground colors relative to the plot background. The default value is set to 1.0. plot-bg-alpha Sets the alpha value of the plot background color relative to the chart background color. The default value is set to 1.0.   Legend Property Group Property name Description show-legend If set to True, displays the legend for the chart. The default value is set to False. location The location of the legend in relation to the chart, which may be set to top, bottom, left, or right. The default location is bottom. legend-border If set to True, renders a border around the legend. The default value is set to True. legend-font The type of Java font to render the legend labels in. legend-bg-color Sets the legend background color. If not set, defaults to white. legend-font-color Sets the legend font color. If not set, defaults to black. Advanced Property Group Property name Description dependencyLevel The dependency level field informs the reporting engine what order the chart should be executed in relation to other items in the report. This is useful if you are using special functions that may need to execute prior to generating the chart. The default value is set to 0. Negative values execute before 0, and positive values execute after 0.   Common category series rendering properties The following properties appear in charts that render category information: Options Property Group Property name Description stacked If set to True, the series values will appear layered on top of one another instead of being displayed relative to one another. stacked-percent If set to True, determines the percentages of each series, and renders the bar height based on those percentages. The property stacked must be set to True for this property to have an effect. General Property Group Property name Description gridlines If set to True, displays category grid lines. This value is set to True by default. X-Axis Property Group Property name Description label-rotation If set, adjusts the inline item label rotation value. The value should be specified in degrees. If not specified, labels are rendered horizontally. You must have show-labels set to true for this value to be relevant. date-format If the item value is a date, a Java date format string may be provided to format the date appropriately. Please see Java's SimpleDateFormat JavaDoc for formatting details. numeric-format If the item value is a decimal number, a Java decimal format string may be provided to format the number appropriately. Please see Java's DecimalFormat JavaDoc for formatting details. text-format The label format used for displaying category items within the chart. This property is required if you would like to display the category item values. The following parameters may be defined in the format string to access details of the item: {0}: To access the Series Name detail of an item {1}: To access the Category detail of an item {2}: To access the Item value details of an item To display just the item value, set the format string to "{2}". x-axis-title If set, displays a label describing the category axis. show-labels If set to true, displays x-axis labels in the chart. x-axis-label-width Sets the maximum category label width ratio, which determines the maximum length each category label should render in. This might be useful if you have really long category names. x-axis-label-rotation If set, adjusts the category item label rotation value. The value should be specified in degrees. If not specified, labels are rendered horizontally. x-font The font to render the category axis title and labels in. Y-Axis Property Group Property name Description y-axis-title If set, displays a label along the value axis of the chart. label-rotation If set, determines the upward angle position of the label, where the value passed into JFreeChart is the mathematical pie over the value. Unfortunately, this property is not very flexible and you may find it difficult to use. y-tick-interval The numeric interval value to separate range ticks in the chart. y-font The font to render the range axis title in. y-sticky-0 If the range includes zero in the axis, making it sticky will force truncation of the axis to zero if set to True. The default value of this property is True. y-incl-0 If set to True, the range axis will force zero to be included in the axis. y-min The minimum value to render in the range axis. y-max The maximum value to render in the range axis. y-tick-font The font to render the range tick value in. y-tick-fmt-str The DecimalFormat string to render the numeric range tick value. enable-log-axis If set to true, displays the y-axis as a logarithmic scale. log-format If set to true, will present the logarithmic scale in a human readable view.
Read more
  • 0
  • 0
  • 5208

article-image-using-javascript-effects-joomla
Packt
06 Nov 2009
7 min read
Save for later

Using JavaScript Effects with Joomla!

Packt
06 Nov 2009
7 min read
Customizing Google Maps Google Maps has a comprehensive API for interacting with maps on your website. MooTools can be used to load the Google Maps engine at the correct time. It can also act as a bridge between the map and other HTML elements on your site. To get started, you will first need to get an API key to use Google Maps on your domain. You can sign up for a free key at http://code.google.com/apis/maps/signup.html. Even if you are working on your local computer, you still need the key. For instance, if the base URL of your Joomla installation is http://localhost/joomla, you will enter localhost as the domain for your API key. Once you have an API key ready, create the file basicmap.js in the /components/com_js folder, and fill it with the following code: window.addEvent('domready', function() { if (GBrowserIsCompatible()) { var map = new GMap2($('map_canvas')); map.setCenter(new GLatLng(38.89, -77.04), 12); window.onunload=function() { GUnload(); }; }}); The entire script is wrapped within a call to the MooTools-specific addEvent() member function of window. Because we want this code to execute once the DOM is ready, the first parameter is the event name 'domready'. The second parameter is an anonymous function containing our code. What does the call to function() do?Using function() in JavaScript is a way of creating an anonymous function. This way, you can create functions that are used in only one place (such as event handlers) without cluttering the namespace with a needless function name. Also, the code within the anonymous function operates within its own scope; this is referred to as a closure. Closures are very frequently used in modern JavaScript frameworks, for event handling and other distinct tasks. Once inside of the function, GBrowserIsCompatible() is used to determine if the browser is capable of running Google Maps. If it is, a new instance of GMap2() is declared and bound to the HTML element that has an id of 'map_canvas' and is stored into map. The call to $('map_canvas') is a MooTools shortcut for document.GetElementById(). Next, the setCenter() member function of map is called to tell Google Maps where to center the map and how far to zoom in. The first parameter is a GLatLng() object, which is used to set the specific latitude and longitude of the map's center. The other parameter determines the zoom level, which is set to 12 in this case. Finally, the window.onunload event is set to a function that calls GUnload(). When the user navigates away from the page, this function removes Google Maps from memory, to prevent memory leaks. With our JavaScript in place, it is now time to add a function to the controller in /components/com_js/js.php that will load it along with some HTML. Add the following basicMap() function to this file: function basicMap(){ $key = 'DoNotUseThisKeyGetOneFromCodeDotGoogleDotCom'; JHTML::_('behavior.mootools'); $document =& JFactory::getDocument(); $document->addScript('http://maps.google.com/maps?file=api&v= 2&key=' . $key); $document->addScript( JURI::base() . 'components/com_js/basicmap.js'); ?> <div id="map_canvas" style="width: 500px; height: 300px"></div> <?php} The basicMap() function starts off by setting $key to the API key received from Google. You should replace this value with the one you receive at http://code.google.com/apis/maps/signup.html. Next, JHTML::_('behavior.mootools'); is called to load MooTools into the <head> tag of the HTML document. This is followed by getting a reference to the current document object through the getDocument() member function of JFactory. The addScript() member function is called twice—once to load in the Google Maps API (using our key), then again to load our basicmap.js script. (The Google Maps API calls in all of the functions and class definitions beginning with a capital 'G'.) Finally, a <div> with an id of 'map_canvas' is sent to the browser. Once this function is in place and js.php has been saved, load index.php?option=com_js&task=basicMap in the browser. Your map should look like this: We can make this map slightly more interesting by adding a marker to a specific address. To do so, add the highlighted code below to the basicmap.js file: window.addEvent('domready', function() { if (GBrowserIsCompatible()) { var map = new GMap2($('map_canvas')); map.setCenter(new GLatLng(38.89, -77.04), 12); var whitehouse = new GClientGeocoder(); whitehouse.getLatLng('1600 Pennsylvania Ave NW', function(latlng) { marker = new GMarker( latlng ); marker.bindInfoWindowHtml('<strong>The White House</strong>'); map.addOverlay(marker); }); window.onunload=function(){ GUnload(); }; }}); This code sets whitehouse as an instance of the GClientGeocoder class. Next, the getLatLng() member function of GClientGeocoder is called. The first parameter is the street address to be looked up. The second parameter is an anonymous function where the GLatLng object is passed once the address lookup is complete. Within this function, marker is set as a new GMarker object, which takes the passed-in latlng object as a parameter. The bindInfoWindowHTML() member function of GMarker is called to add an HTML message to appear in a balloon above the marker. Finally, the maker is passed into the addOverlay() member function of GMap2, to place it on the map. Save basicmap.js and then reload index.php?option=com_js&task=basicMap. You should now see the same map, only with a red pin. When you click on the red pin, your map should look like this: Interactive Maps These two different maps show the basic functionality of getting Google Maps on your own website. These maps are very basic; you could easily create them at maps.google.com then embed them in a standard Joomla! article with the HTML code they provide you. However, you would not have the opportunity to add functions that interact with the other elements on your page. To do that, we will create some more HTML code and then write some MooTools-powered JavaScript to bridge our content with Google Maps. Open the /components/com_js/js.php file and add the following selectMap() function to the controller: function selectMap(){ $key = 'DoNotUseThisKeyGetOneFromCodeDotGoogleDotCom'; JHTML::_('behavior.mootools'); $document =& JFactory::getDocument(); $document->addScript('http://maps.google.com/maps?file=api&v =2&key=' . $key); $document->addScript( JURI::base() . 'components/com_js/selectmap.js'); ?> <div id="map_canvas" style="width: 500px; height: 300px"></div> <select id="map_selections"> <option value="">(select...)</option> <option value="1200 K Street NW">Salad Surprises</option> <option value="1221 Connecticut Avenue NW">The Daily Dish</option> <option value="701 H Street NW">Sushi and Sashimi</option> </select><?php} This function is almost identical to basicMap() except for two things—selectmap.js is being added instead of basicmap.js, and a <select> element has been added beneath the <div>. The <select> element has an id that will be used in the JavaScript. The options of the <select> element are restaurants, with different addresses as values. The JavaScript code will bind a function to the onChange event so that the marker will move as different restaurants are selected.
Read more
  • 0
  • 0
  • 5030

article-image-including-charts-and-graphics-pentaho-reports-part-2
Packt
29 Oct 2009
6 min read
Save for later

Including Charts and Graphics in Pentaho Reports (Part 2)

Packt
29 Oct 2009
6 min read
Ring chart The ring chart is identical to the pie chart, except that it renders as a ring versus a complete pie. In addition to sharing all the properties similar to the pie chart, it also defines the following rendering property : Options Property Group Property name Description section-depth This property defines the percentage of the radius to render the section as. The default value is set to 0.5. Ring chart example For this example, simply open the defined pie chart example and select the Ring chart type. Also, set the section-depth to 0.1, in order to generate the following effect: Multi pie chart The multi pie chart renders a group of pie charts, based on a category dataset. This meta-chart renders individual series data as a pie chart, each broken into individual categories within the individual pie charts. The multi pie chart utilizes the common properties defined above, including the category dataset properties. In addition to the standard set of properties, it also defines the following two properties: Options Property Group Property name Description label-format This label defines how each item within a chart is rendered. The default value is set to "{0}". The format string may also contain any of the following: {0}: To render the item name {1}: To render the item value {2}: To render the item percentage in relation to the entire pie chart by-row This value defaults to True. If set to False, the series and category fields are reversed, and individual charts render series information. Note that the horizontal, series-color, stacked and stacked-percent properties do not apply to this chart type. Multi pie chart example This example demonstrates the distribution of purchased item types, based on payment type. To begin, create a new report. You'll reuse the bar chart's SQL query. Now, place a new Chart element into the Report Header. Edit the chart, selecting Multi Pie as the chart type. To configure the dataset for this chart, select ITEMCATEGORY as the category-column. Set the value-columns property to QUANTITY and the series-by-field to PAYMENTTYPE. Waterfall chart The waterfall chart displays a unique stacked bar chart that spans categories. This chart is useful when comparing categories to one another. The last category in a waterfall chart normally equals the total of all the other categories to render appropriately, but this is based on the dataset, not the chart rendering. The waterfall chart utilizes the common properties defined above, including the category dataset properties. The stacked property is not available for this chart. There are no additional properties defined for the waterfall chart. Waterfall chart example In this example, you'll compare by type, the quantity of items in your inventory. Normally, the last category would be used to display the total values. The chart will render the data provided with or without a summary series, so you'll just use the example SQL query from the bar chart example. Add a Chart element to the Report Header and select Waterfall as the chart type. Set the category-column to ITEMCATEGORY, the value-columns to QUANTITY, and the series-by-value property to Quantity. Now, apply your changes and preview the results. Bar line chart The bar line chart combines the bar and line charts, allowing visualization of trends with categories, along with comparisons. The bar line chart is unique in that it requires two category datasets to populate the chart. The first dataset populates the bar chart, and the second dataset populates the line chart. The bar line chart utilizes the common properties defined above, including the category dataset properties. This chart also inherits the properties from both the bar chart, as well as the line chart. This chart also has certain additional properties, which are listed in the following table: Required Property Group Property name Description bar-data-source The name of the first dataset required by the bar line chart, which populates the bars in the chart. This value is automatically populated with the correct name. line-data-source The name of the second dataset required by the bar line chart, which populates the lines in the chart. This value is automatically populated with the correct name. Bar Options Property Group Property name Description ctgry-tick-font Defines the Java font that renders the Categories. Line Options Property Group Property name Description line-series-color Defines the color in which to render each line series. line-tick-fmt Specifies the Java DecimalFormat string for rendering the Line Axis Labels lines-label-font Defines the Java font to use when rendering line labels. line-tick-font Defines the Java font to use when rendering the Line Axis Labels. As part of the bar line chart, a second y-axis is defined for the lines. The property group Y2-Axis is available with similar properties as the standard y-axis. Bar line chart example To demonstrate the bar line chart, you'll reuse the SQL query from the area chart example. Create a new report, and add a Chart element to the Report Header. Edit the chart, and select Bar Line as the chart type. You'll begin by configuring the first dataset. Set the category-column to ITEMCATEGORY, the value-columns to COST, and the series-by-value property to Cost. To configure the second dataset, set the category-column to ITEMCATEGORY, the value-columns to SALEPRICE, and the series-by-value property to Sale Price. Set the x-axis-label-width to 2.0, and reduce the x-font size to 7. Also, set show-legend to True. You're now ready to preview the bar line chart. Bubble chart The bubble chart allows you to view three dimensions of data. The first two dimensions are your traditional X and Y dimensions, also known as domain and range. The third dimension is expressed by the size of the individual bubbles rendered. The bubble chart utilizes the common properties defined above, including the XY series dataset properties. The bubble chart also defines the following properties: Options Property Group Property name Description max-bubble-size This value defines the diameter of the largest bubble to render. All other bubble sizes are relative to the maximum bubble size. The default value is 0, so this value must be set to a reasonable value for rendering of bubbles to take place. Note that this value is based on pixels, not the domain or range values. The bubble chart defines the following additional dataset property: Required Property Group Property name Description z-value-columns This is the data source column to use for Z value, which specifies the bubble diameter relative to the maximum bubble size. Bubble chart example In this example, you need to define a three dimensional SQL query to populate the chart. You'll use inventory information, and calculate Item Category Margin: SELECT"INVENTORY"."ITEMCATEGORY","INVENTORY"."ONHAND","INVENTORY"."ONORDER","INVENTORY"."COST","INVENTORY"."SALEPRICE","INVENTORY"."SALEPRICE" - "INVENTORY"."COST" MARGINFROM"INVENTORY"ORDER BY"INVENTORY"."ITEMCATEGORY" ASC Now that you have a SQL query to work with, add a Chart element to the Report Header and select Bubble as the chart type. First, you'll populate the correct dataset fields. Set the series-by-field property to ITEMCATEGORY. Now, set the X, Y, and Z value columns to ONHAND, SALEPRICE, and MARGIN. You're now ready to customize the chart rendering. Set the x-title to On Hand, the y-title to Sales Price, the max-bubble-size to 100, and the show-legend property to True. The final result should look like this:
Read more
  • 0
  • 0
  • 4011

article-image-understanding-business-activity-monitoring-oracle-soa-suite
Packt
28 Oct 2009
14 min read
Save for later

Understanding Business Activity Monitoring in Oracle SOA Suite

Packt
28 Oct 2009
14 min read
How BAM differs from traditional business intelligence The Oracle SOA Suite stores the state of all processes in a database in documented schemas so why do we need yet another reporting tool to provide insight into our processes and services? In other words how does BAM differ from traditional BI (Business Intelligence)? In traditional BI, reports are generated and delivered either on a scheduled basis or in response to a user request. Any changes to the information will not be reflected until the next scheduled run or until a user requests the report to be rerun. BAM is an event-driven reporting tool that generates alerts and reports in real time, based on a continuously changing data stream, some of whose data may not be in the database. As events occur in the Services and Processes, the business has defined they are captured by BAM and reports and views are updated in real time. Where necessary these updated reports are delivered to users. This delivery to users can take several forms. The best known is the dashboard on users' desktops that will automatically update without any need for the user to refresh the screen. There are also other means to deliver reports to the end user, including sending them via a text message or an email. Traditional reporting tools such as Oracle Reports and Oracle Discoverer as well as Oracles latest Business Intelligence Suite can be used to provide some real-time reporting needs but they do not provide the event driven reporting that gives the business a continuously updating view of the current business situation. Event Driven Architecture Event Driven Architecture (EDA) is about building business solutions around responsiveness to events. Events may be simple triggers such as a stock out event or they may be more complex triggers such as the calculations to realize that a stock out will occur in three days. An Event Driven Architecture will often take a number of simple events and then combine them through a complex event processing sequence to generate complex events that could not have been raised without aggregation of several simpler events. Oracle BAM scenarios Oracle Business Activity Monitoring is typically used to monitor two distinct types of real-time data. Firstly it may be used to monitor the overall state of processes in the business. For example it may be used to track how many auctions are currently running, how many have bids on them, and how many have completed in the last 24 hours (or other time periods). Secondly it may be used to track in real-time Key Performance Indicators or KPIS. For example it may be used to provide a real-time updating dashboard to a seller to show the current total value of all the sellers' auctions and to track this against an expected target. In the first case, we are interested in how business processes are progressing and are using BAM to identify bottlenecks and failure points within those processes. Bottlenecks can be identified by too much time being spent on given steps in the process. BAM allows us to compute the time taken between two points in a process, such as the time between order placement and shipping, and provide real-time feedback on those times. Similarly BAM can be used to track the percentage drop-out rate between steps in a sales process, allowing the business to take appropriate action. In the second case, our interest is on some aggregate number, such as our total liabilities should we win all the auctions we are bidding on. This requires us to aggregate results from many events, possibly performing some kind of calculation on them to provide us with a single KPI that gives an indication to the business of how things are going. BAM allows us to continuously update this number in real on a dashboard without the need for continued polling. It also allows us to trigger alerts, perhaps through email or SMS, to notify an individual, when a threshold is breached. In both cases reports delivered can be customized based on the individual receiving the report. BAM architecture It may seem odd to have a section on architecture in the middle of a article about how to effectively use BAM, but key to successful utilization of BAM is an understanding of how the different tiers relate to each other. Logical view The following diagram represents a logical view of how BAM operates. Events are acquired from one or more sources through event acquisition and then normalized, correlated, and stored in event storage (generally a memory area in BAM that is backed up to disc). The report cache generates reports based on events in storage and then delivers those reports, together with real-time updates through the report delivery layer. Event processing is also performed on events in storage, and when defined conditions are met, alerts will be delivered through the alert delivery service. Physical view To better understand the physical view of the architecture of BAM, we have divided this section into four parts. Let us discuss these in detail. Capture This logical view maps onto the physical BAM components shown in the following diagram. Data acquisition in the SOA Suite is handled by sensors in BPEL and ESB. BAM can also receive events from JMS message queues and access data in databases (useful for historical comparison). For complex data formats or for other data sources then Oracle Data Integrator (ODI is a separate product to the SOA Suite) is recommended by Oracle. Although potentially less efficient and more work than running ODI, it is also possible to use adapters to acquire data from multiple sources and feed it into BAM through ESB or BPEL. At the data capture level we need to think of the data items that we can provide to feed the reports and alerts that we desire to generate. We must consider the sources of that data and the best way to load it into BAM. Store Once the data is captured, it is then stored in a normalized form in the Active Data Cache (ADC). This storage facility has the ability to do simple correlation based on fields within the data, and multiple data items received from the acquisition layer may update just a single object in the data cache. For example the state of a given BPEL process instance may be represented by a single object in the ADC and all updates to that process state will just update that single data item rather than creating multiple data items. Process Reports are run based on user demand. Once a report is run it will update the user's screen on a real time basis. Where multiple users are accessing the same report only one instance of the report is maintained by the report server. As events are captured and stored in real time the report engine will continuously monitor them for any changes that need to be made to those reports which are currently active. When changes are detected that impact active reports, then the appropriate report will be updated in memory and the updates sent to the user screen. In addition to the event processing required to correctly insert and update items in the ADC, there is also a requirement to monitor items in the ADC for events that require some sort of action to be taken. This is the job of the event processor. This will monitor data in the ADC to see if registered thresholds on values have been exceeded or if certain time-outs have expired. The event processor will often need to perform calculations across multiple data items to do this. Deliver Delivery of reports takes place in two ways. First, users request reports to be delivered to their desktop by selecting views within BAM. These reports are delivered as HTML pages within a browser and are updated whenever the underlying data used in the report changes. The second approach is that reports are sent out as a result of events being triggered by the Event Processing Engine. In the latter case, the report may be delivered by email, SMS, or voice messaging using the notifications service. A final option available for these event generated reports is to invoke a web service to take some sort of automated action. Closing the loop While monitoring what is happening is all very laudable, it is only of benefit if we actually do something about what we are monitoring. BAM provides the real-time monitoring ability very well but it also provides the facility to invoke other services to respond to undesirable events such as stock outs. The ability to invoke external services is crucial to the concept of a closed loop control environment where as a result of monitoring we are able to reach back into the processes and either alter their execution or start new ones. For example when a stock out or low stock event is raised then the message centre could invoke a web service requesting a supplier to send more stock to replenish inventory. Placing this kind of feedback mechanism in BAM allows us to trigger events across multiple applications and locations in a way that may not be possible within a single application or process. For example, in response to a stock out, instead of requesting our supplier to provide more stock, we may be monitoring stock levels in independent systems and, based on stock levels elsewhere, may redirect stock from one location to another. BAM platform anomaly In 10g SOA Suite, BAM runs only as a Windows application. Unlike the rest of SOA Suite, it does not run on a JEE Application Server and it can only run on the Windows platform. In the next release, 11g, BAM will be provided as a JEE application that can run on a number of application servers and operating systems. User interface Development in Oracle BAM is done through a web-based user interface. This user interface gives access to four different applications that allow you to interact with different parts of BAM. These are: Active Viewer for giving access to reports; this relates to the deliver stage for user requested reports. Active Studio for building reports; this relates to the 'process' stage for creating reports. Architect for setting up both inbound and outbound events. Data elements are defined here as data sources. Alerts are also configured here. This covers setting up, acquire and store stages as well as the deliver stage for alerts. Administrator for managing users and roles as well as defining the types of message sources. We will not examine the applications individually but will take a task-focused look at how to use them as part of providing some specific reports. Monitoring process state Now that we have examined how BAM is constructed, let us use this knowledge to construct some simple dashboards that track the state of a business process. We will instrument a simple version of an auction process. The process is shown in the following figure: An auction is started and then bids are placed until the time runs out at which point the auction is completed. This is modelled in BPEL. This process has three distinct states: Started Bid received Completed We are interested in the number of auctions in each state as well as the total value of auctions in progress. One needs to follow these steps to build the dashboard: Define our data within the Active Data Cache Create sensors in BPEL and map to data in the ADC Create suitable reports Run the reports Defining data objects Data in BAM is stored in data objects. Individual data objects contain the information that is reported in BAM dashboards and may be updated by multiple events. Generally BAM will report against aggregations of objects, but there is also the ability for reports to drill down into individual data objects. Before defining our data objects let's group them into an Auction folder so they are easy to find. To do this we use the BAM Architect application and select Data Objects which gives us the following screen: We select Create subfolder to create the folder and give it a name Auction. We then select Create folder to actually create the folder and we get a confirmation message to tell us that the folder was created. Notice that once created, the folder also appears in the Folders window on the left-hand side of the screen. Now we have our folder we can create a data object. Again we select Data Objects from the drop-down menu. To define the data objects that are to be stored in our Active Data Cache, we open the Auction folder if it is not already open and selectCreate Data Object. If we don't select the Auction folder then we pick it later when filling in the details of the data object. We need to give our object a unique name within the folder and optionally provide it with a tip text that helps explain what the object does when the mouse is moved over it in object listings. Having named our object we can now create the data fields by selecting Add a field. When adding fields we need to provide a name and type as well as indicating if they must contain data; the default Nullable does not require a field to be populated. We may also optionally indicate if a field should be public "available for display" and what if any tool tip text it should have. Once all the data fields have been defined then we can click Create Data Object to actually create the object as we have defined it. We are then presented with a confirmation screen that the object has been created. Grouping data into hierarchies When creating a data object it is possible to specify Dimensions for the object. A dimension is based on one or more fields within the object. A given field can only participate in one dimension. This gives the ability to group the object by the fields in the given dimension. If multiple fields are selected for a single dimension then they can be layered into a hierarchy, for example to allow analysis by country, region, and city. In this case all three elements would be selected into a single dimension, perhaps called geography. Within geography a hierarchy could be set up with country at the top, region next, and finally city at the bottom, allowing drill down to occur in views. Just as a data object can have multiple dimensions, a dimension can also have multiple hierarchies. A digression on populating data object fields In the previous discussion, we mentioned the Nullable attribute that can be attached to fields. This is very important as we do not expect to populate all or even most of the fields in a data object at one moment in time. Do not confuse data objects with the low level events that are used to populate them. Data objects in BAM do not have a one-to-one correspondence with the low level events that populate them. In our auction example there will be just one auction object for every auction. However there will be at least two and usually more messages for every auction; one message for the auction starting, another for the auction completing, and additional messages for each bid received. These messages will all populate or in some cases overwrite different parts of the auction data object. The table shows how the three messages populate different parts of the data object. Message Auction ID State Highest bid Reserve Expires Seller Highest bidder Auction Started Inserted Inserted Inserted Inserted Inserted Inserted   Bid Received   Updated Updated       Updated Auction Finished   Updated           Summary In this article we have explored how Business Activity Monitoring differs from and is complementary to more traditional Business Intelligence solutions such as Oracle Reports and Business Objects. We have explored how BAM can allow the business to monitor the state of business targets and Key Performance Indicators, such as the current most popular products in a retail environment or the current time taken to serve customers in a service environment.
Read more
  • 0
  • 0
  • 7172
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-using-business-rules-define-decision-points-oracle-soa-suite-part-2
Packt
28 Oct 2009
6 min read
Save for later

Using Business Rules to Define Decision Points in Oracle SOA Suite: Part 2

Packt
28 Oct 2009
6 min read
To invoke a rule we need to go through a number of steps. First we must create a session with the rules engine, then we can assert one or more facts, before executing the rule set and finally we can retrieve the results. We do this in BPEL via a Decision Service; this is essentially a web service wrapper around a rules dictionary, which takes cares of managing the session with the rules engine as well as governing which rule set we wish to apply. The wrapper allows a BPEL process to assert one or more facts, execute a rule set against the asserted facts, retrieve the results and then reset the session. This can be done within a single invocation of an operation, or over multiple operations. Creating a Rule Engine Connection Before you can create a Decision Service you need to create a connection to the repository in which the required rule set is stored. In the Connections panel within JDeveloper, right-click on the Rule Engines folder and select New Rule Engine Connection… as shown in the following screenshot: This will launch the Create Rule Engine Connection dialogue; first you need to specify whether the connection is for a file repository or WebDAV repository. Using a file based repository If you are using a file repository, all we need to specify is the location of the actual file. Once the connection has been created, we can use this to create a decision service for any of the rule sets contained within that repository. However, it is important to realize that when you create a decision service based on this connection, JDeveloper will take a copy of the repository and copy this into the BPEL project. When you deploy the BPEL process, then the copy of this repository will be deployed with the BPEL process. This has a number of implications; first if you want to modify the rule set used by the BPEL Process you need to modify the copy of the repository deployed with the BPEL Process. To modify the rule set deployed with a BPEL Process, log onto the BPEL console, from here click on the BPEL Processes tab, and then select the process that uses the decision service. Next click on the Descriptor tab; this will list all the Partner Links for that process, including the Decision Service (for example LeaveApprovalDecisionServicePL) as shown in the following screenshot: This PartnerLink will have the property decisionServiceDetails, with the link Rule Service Details (circled in the previous screenshot); click on this and the console will display details of the decision service. From here click on the link Open Rule Author; this will open the Rule Author complete with a connection to the file based rule repository. The second implication is that if you use the same rule set within multiple BPEL Processes, each process will have its own copy of the rule set. You can work round this by either wrapping each rule set with a single BPEL process, which is then invoked by any other process wishing to use that rule set. Or once you have deployed the rule set for one process, then you can access it directly via the WSDL for the deployed rule set, for example LeaveApprovalDecisionService.wsdl in the above screenshot. Using a WebDAV repository For the reasons mentioned above, it often makes sense to use a WebDAV based repository to hold your rules. This makes it far simpler to share a rule set between multiple clients, such as BPEL and Java. Before you can create a Rule Engine Connection to a WebDAV repository, you must first define a WebDAV connection to JDeveloper, which is also created from the Connections palette. Creating a Decision Service To create a decision service within our BPEL process, select the Services page from the Component Palette and drag a Decision Service onto your process, as shown in the following screenshot: This will launch the Decision Service Wizard dialogue, as shown: Give the service a name, and then select Execute Ruleset as the invocation pattern. Next click on the flashlight next to Ruleset to launch the Rule Explorer. This allows us to browse any previously defined rule engine connection and select the rule set we wish to invoke via the decision service. For our purposes, select the LeaveApprovalRules as shown below, and click OK. This will bring us back to the Decision Service Wizard which will be updated to list the facts that we can exchange with the Rule Engine, as shown in the following screenshot: This dialogue will only list XML Facts that map to global elements in the XML Schema. Here we need to define which facts we want to assert, that is which facts we pass as inputs to the rule engine from BPEL, and which facts we want to watch, that is which facts we want to return in the output from the rules engine back to our BPEL process. For our example, we will pass in a single leave request. The rule engine will then apply the rule set we defined earlier and update the status of the request to Approved if appropriate. So we need to specify that Assert and Watch facts of type LeaveRequest. Finally, you will notice the checkbox Check here to assert all descendants from the top level element; this is important when an element contains nested elements (or facts) to ensure that nested facts are also evaluated by the rules engine. For example if we had a fact of type LeaveRequestList which contained a list of multiple LeaveRequests, if we wanted to ensure the rules engine evaluated these nested facts, then we would need to check this checkbox. Once you have specified the facts to Assert and Watch, click Next and complete the dialogue; this will then create a decision service partner link within your BPEL process. Adding a Decide activity We are now ready to invoke our rule set from within our BPEL process. From the Component Palette, drag a Decide activity onto our BPEL process (at the point before we execute the LeaveRequest Human Task). This will open up the Edit Decide window (shown in the following screenshot). Here we need to specify a Name for the activity, and select the Decision Service we want to invoke (that is the LeaveApprovalDecisionService that we just created). Once we've specified the service, we need to specify how we want to interact with it. For example, whether we want to incrementally assert a number of facts over a period of time, before executing the rule set and retrieving the result or whether we want to assert all the facts, execute the rule set and get the result within a single invocation. We specify this through the Operation attribute. For our purpose we just need to assert a single fact and run the rule set, so select the value of Assert facts, execute rule set, retrieve results. Once we have selected the operation to invoke on the decision service, the Decision Service Facts will be updated to allow you to assign input and output facts as appropriate.  
Read more
  • 0
  • 0
  • 2151

article-image-telecommunications-and-network-security-concepts-cissp-exam
Packt
28 Oct 2009
5 min read
Save for later

Telecommunications and Network Security Concepts for CISSP Exam

Packt
28 Oct 2009
5 min read
Transport layer The transport layer in the TCP/IP model does two things: it packages the data given out by applications to a format that is suitable for transport over the network, and it unpacks the data received from the network to a format suitable for applications. The process of packaging the data packets received from the applications is known as encapsulation. The output of such a process is known as datagram. Similarly, the process of unpacking the datagram received from the network is known as abstraction A transport section in a protocol stack carries the information that is in the form of datagrams, Frames and Bits. Transport layer protocols There are many transport layer protocols that carry the transport layer functions. The most important ones are: Transmission Control Protocol (TCP): It is a core Internet protocol that provides reliable delivery mechanisms over the Internet. TCP is a connection-oriented protocol. User Datagram Protocol (UDP): This protocol is similar to TCP, but is connectionless. A connection-oriented protocol is a protocol that guarantees delivery of datagram (packets) to the destination application by way of a suitable mechanism. For example, a three-way handshake syn, syn-ack, ack in TCP. The reliability of datagram delivery of such protocol is high. A protocol that does not guarantee the delivery of datagram, or packets, to the destination is known as connectionless protocol. These protocols use only one-way communication. The speed of the datagram's delivery by such protocols is high. Other transport layer protocols are as follows: Sequenced Packet eXchange (SPX): SPX is a part of the IPX/SPX protocol suit and used in Novell NetWare operating system. While Internetwork Packet eXchange (IPX) is a network layer protocol, SPX is a transport layer protocol. Stream Control Transmission Protocol (SCTP): It is a connection-oriented protocol similar to TCP, but provides facilities such as multi-streaming and multi-homing for better performance and redundancy. It is used in Unix-like operating systems. Appletalk Transaction Protocol (ATP): It is a proprietary protocol developed for Apple Macintosh computers. Datagram Congestion Control Protocol (DCCP): As the name implies, it is a transport layer protocol used for congestion control. Applications include Internet telephony and video or audio streaming over the network. Fiber Channel Protocol (FCP): This protocol is used in high-speed networking such as Gigabit networking. One of its prominent applications is Storage Area Network (SAN). SAN is network architecture that's used for attaching remote storage devices such as tape drives, disk arrays, and so on to the local server. This facilitates the use of storage devices as if they were local devices. In the following sections we'll review the most important protocols—TCP and UDP. Transmission Control Protocol (TCP) TCP is a connection-oriented protocol that is widely used in Internet communications. As the name implies, a protocol has two primary functions. The primary function of TCP is the transmission of datagram between applications, while the secondary function is related to controls that are necessary for ensuring reliable transmissions. Protocol / Service Transmission Control Protocol (TCP) Layer(s) TCP works in the transport layer of the TCP/IP model Applications Applications where the delivery needs to be assured such as email, World Wide Web (WWW), file transfer, and so on use TCP for transmission Threats Service disruption Vulnerabilities Half-open connections Attacks Denial-of- service attacks such as TCP SYN attacks Connection hijacking such as IP Spoofing attacks Countermeasures Syn cookies Cryptographic solutions   A half-open connection is a vulnerability in TCP implementation. TCP uses a three-way handshake to establish or terminate connections. Refer to the following illustration: In a three-way handshake, first the client (workstation) sends a request to the server (www.some_website.com). This is known as an SYN request. The server acknowledges the request by sending SYN-ACK and, in the process, creates a buffer for that connection. The client does a final acknowledgement by sending ACK. TCP requires this setup because the protocol needs to ensure the reliability of packet delivery. If the client does not send the final ACK, then the connection is known as half-open. Since the server has created a buffer for that connection, certain amounts of memory or server resources are consumed. If thousands of such half-open connections are created maliciously, the server resources may be completely consumed resulting in a denial-of-service to legitimate requests. TCP SYN attacks are technically establishing thousands of half-open connections to consume the server resources. Two actions can be taken by an attacker. The attacker, or malicious software, will send thousands of SYN to the server and withhold the ACK. This is known as SYN flooding. Depending on the capacity of the network bandwidth and the server resources, in a span of time the entire resources will be consumed. This will result in a denial-of-service. If the source IP were blocked by some means, then the attacker, or the malicious software, would try to spoof the source IP addresses to continue the attack. This is known as SYN spoofing. SYN attacks, such as SYN flooding and SYN spoofing, can be controlled using SYN cookies with cryptographic hash functions. In this method, the server does not create the connection at the SYN-ACK stage. The server creates a cookie with the computed hash of the source IP address, source port, destination IP, destination port, and some random values based on an algorithm, which it sends as SYN-ACK. When the server receives an ACK, it checks the details and creates the connection. A cookie is a piece of information, usually in a form of text file, sent by the server to client. Cookies are generally stored on a client's computer and are used for purposes such as authentication, session tracking, and management. User Datagram Protocol (UDP) UDP is a connectionless protocol similar to TCP. However, UDP does not provide delivery guarantee of data packets.  
Read more
  • 0
  • 0
  • 4517

article-image-designing-your-very-own-aspnet-mvc-application
Packt
28 Oct 2009
8 min read
Save for later

Designing your very own ASP.NET MVC Application

Packt
28 Oct 2009
8 min read
When downloading and installing the ASP.NET MVC framework SDK, a new project template is installed in Visual Studio—the ASP.NET MVC project template. This article by Maarten Balliauw describes how to use this template. We will briefly touch all aspects of ASP.NET MVC by creating a new ASP.NET MVC web application based on this Visual Studio template. Besides view, controller, and model, new concepts including ViewData—a means of transferring data between controller and view, routing—the link between a web browser URL and a specific action method inside a controller, and unit testing of a controller are also illustrated in this article. (For more resources on .NET, see here.) Creating a new ASP.NET MVC web application project Before we start creating an ASP.NET MVC web application, make sure that you have installed the ASP.NET MVC framework SDK from http://www.asp.net/mvc. After installation, open Visual Studio 2008 and select menu option File | New | Project. The following screenshot will be displayed. Make sure that you select the .NET framework 3.5 as the target framework. You will notice a new project template called ASP.NET MVC Web Application. This project template creates the default project structure for an ASP.NET MVC application. After clicking on OK, Visual Studio will ask you if you want to create a test project. This dialog offers the choice between several unit testing frameworks that can be used for testing your ASP.NET MVC application. You can decide for yourself if you want to create a unit testing project right now—you can also add a testing project later on. Letting the ASP.NET MVC project template create a test project now is convenient because it creates all of the project references, and contains an example unit test, although this is not required. For this example, continue by adding the default unit test project. What's inside the box? After the ASP.NET MVC project has been created, you will notice a default folder structure. There's a Controllers folder, a Models folder, a Views folder, as well as a Content folder and a Scripts folder. ASP.NET MVC comes with the convention that these folders (and namespaces) are used for locating the different blocks used for building the ASP.NET MVC framework. The Controllers folder obviously contains all of the controller classes; the Models folder contains the model classes; while the Views folder contains the view pages. Content will typically contain web site content such as images and stylesheet files, and Scripts will contain all of the JavaScript files used by the web application. By default, the Scripts folder contains some JavaScript files required for the use of Microsoft AJAX or jQuery. Locating the different building blocks is done in the request life cycle. One of the first steps in the ASP.NET MVC request life cycle is mapping the requested URL to the correct controller action method. This process is referred to as routing. A default route is initialized in the Global.asax file and describes to the ASP.NET MVC framework how to handle a request. Double-clicking on the Global.asax file in the MvcApplication1 project will display the following code: using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace MvcApplication1{ public class GlobalApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = "" } // Parameter defaults ); } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } }} In the Application_Start() event handler, which is fired whenever the application is compiled or the web server is restarted, a route table is registered. The default route is named Default, and responds to a URL in the form of http://www.example.com/{controller}/{action}/{id}. The variables between { and } are populated with actual values from the request URL or with the default values if no override is present in the URL. This default route will map to the Home controller and to the Index action method, according to the default routing parameters. We won't have any other action with this routing map. By default, all the possible URLs can be mapped through this default route. It is also possible to create our own routes. For example, let's map the URL http://www.example.com/Employee/Maarten to the Employee controller, the Show action, and the firstname parameter. The following code snippet can be inserted in the Global.asax file we've just opened. Because the ASP.NET MVC framework uses the first matching route, this code snippet should be inserted above the default route; otherwise the route will never be used. routes.MapRoute( "EmployeeShow", // Route name "Employee/{firstname}", // URL with parameters new { // Parameter defaults controller = "Employee", action = "Show", firstname = "" } ); Now, let's add the necessary components for this route. First of all, create a class named EmployeeController in the Controllers folder. You can do this by adding a new item to the project and selecting the MVC Controller Class template located under the Web | MVC category. Remove the Index action method, and replace it with a method or action named Show. This method accepts a firstname parameter and passes the data into the ViewData dictionary. This dictionary will be used by the view to display data. The EmployeeController class will pass an Employee object to the view. This Employee class should be added in the Models folder (right-click on this folder and then select Add | Class from the context menu). Here's the code for the Employee class: namespace MvcApplication1.Models{ public class Employee { public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } }} After adding the EmployeeController and Employee classes, the ASP.NET MVC project now appears as shown in the following screenshot: The EmployeeController class now looks like this: using System.Web.Mvc;using MvcApplication1.Models;namespace MvcApplication1.Controllers{ public class EmployeeController : Controller { public ActionResult Show(string firstname) { if (string.IsNullOrEmpty(firstname)) { ViewData["ErrorMessage"] = "No firstname provided!"; } else { Employee employee = new Employee { FirstName = firstname, LastName = "Example", Email = firstname + "@example.com" }; ViewData["FirstName"] = employee.FirstName; ViewData["LastName"] = employee.LastName; ViewData["Email"] = employee.Email; } return View(); } }} The action method we've just created can be requested by a user via a URL—in this case, something similar to http://www.example.com/Employee/Maarten. This URL is mapped to the action method by the route we've created before. By default, any public action method (that is, a method in a controller class) can be requested using the default routing scheme. If you want to avoid a method from being requested, simply make it private or protected, or if it has to be public, add a [NonAction] attribute to the method. Note that we are returning an ActionResult (created by the View() method), which can be a view-rendering command, a page redirect, a JSON result, a string, or any other custom class implementation inheriting the ActionResult that you want to return. Returning an ActionResult is not necessary. The controller can write content directly to the response stream if required, but this would be breaking the MVC pattern—the controller should never be responsible for the actual content of the response that is being returned. Next, create a Show.aspx page in the Views | Employee folder. You can create a view by adding a new item to the project and selecting the MVC View Content Page template, located under the Web | MVC category, as we want this view to render in a master page (located in Views | Shared). There is an alternative way to create a view related to an action method, which will be covered later in this article. In the view, you can display employee information or display an error message if an employee is not found. Add the following code to the Show.aspx page: <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" Inherits=" System.Web.Mvc.ViewPage" %><asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <% if (ViewData["ErrorMessage"] != null) { %> <h1><%=ViewData["ErrorMessage"]%></h1> <% } else { %> <h1><%=ViewData["FirstName"]%> <%=ViewData["LastName"]%></h1> <p> E-mail: <%=ViewData["Email"]%> </p> <% } %></asp:Content> If the ViewData, set by the controller, is given an ErrorMessage, then the ErrorMessage is displayed on the resulting web page. Otherwise, the employee details are displayed. Press the F5 button on your keyboard to start the development web server. Alter the URL in your browser to something ending in /Employee/Your_Name_Here, and see the action method and the view we've just created in action.
Read more
  • 0
  • 0
  • 6445

article-image-adding-calendar-web-site-using-drupal-6
Packt
28 Oct 2009
11 min read
Save for later

Adding Calendar to a Web Site using Drupal 6

Packt
28 Oct 2009
11 min read
Adding new events to the calendar Good Eatin' Goal: Create an event that will be displayed on the calendar. Additional modules needed: Event (http://drupal.org/project/event). Basic steps In order to add an event, you must first install and activate the Event module in the Module manager as shown in the following screenshot: Activating the Event module will a create a new Event content type. There are also several settings that control how events are displayed and how time zones are handled. To modify the time zone settings, select Site configuration, then Events, and finally Timezone handling, from the Administer menu. Drupal will display a page similar to the following: You will want to customize these settings according to where the majority of your users live, and the types of events that you are holding. For example, if most of your users are in the U.S., 12 hour notation is probably appropriate, but if most of you users are in Europe, 24 hour notation is better. If the events are held online with a mix of users in different time zones, it would make sense to have the events displayed in the user's time zone. However, if the event is being held at a single site, it would make sense to use the local time of the event. For the Good Eatin' site, we will use the site's time zone for events, display the events in the event time zone, and use the 12 hour time notification. Before we can create an event, we must set the default time zone for the site. This is done by selecting Site configuration and then Date and time, from the Administer menu. The Good Eatin' restaurant is located in Colorado, so we will set the time zone to US/Mountain. Click Save configuration to save your changes. To add an event, select Create content and then Event, from the main Navigation menu. Enter a title and a description for the event, as shown in the following screenshot, and then set the start time and optionally the end time for the event. Click Save when you are happy with the event settings. Displaying events Good Eatin' Goal: Display events on the site in various formats including a block of upcoming events, a table of events, and a calendar of events. Additional modules needed: Event (http://drupal.org/project/event). Basic steps The Event module provides several methods for allowing customers to view events. We will explore each of these in turn. The easiest way to allow visitors to browse events is by using the event page, which is accessed by at http://yoursite.com/event. The page appears as follows: If you want the user to be able to access this page without knowing the URL in advance, you can create a menu item for the page. Open the Menu Manager by selecting on Site building and then menus, from the Administer menu. Select the menu that you want to add to the menu item and then click the Add item tab. Enter the information about the new menu item, as shown in the following screenshot, and then click Save when you are satisfied. The second method of presenting events to users is by using the upcoming events block. To add this, open the Blocks Manager by selecting Site building and then Blocks, from the Administer menu. Set the region for the List of upcoming events to Right sidebar. The new block will appear as follows: The final method of displaying calendar entries is a block showing upcoming events in a calendar view. To add this block, open the Block Manager by selecting Site building and then Blocks, from the Administer menu. Set the region for Calendar to browse events to Right sidebar. The display for the calendar will appear as follows: You can decide which of these methods to use for your own site, based on how the user will work with your site. Adding other content types to the event calendar Good Eatin' Goal: Discuss how to add custom content types to the event calendar. Additional modules needed: Event (http://drupal.org/project/event). An easy way of adding additional content types to your existing event calendar is by modifying the content type and then setting the Event calendar options. Open the Content Manager by selecting Content management and thenContent types, from the Administer menu. Edit the type that you want to add to the event calendar. Open the Event calendar section and modify the options, as shown here: If you prefer to have a calendar just for the type, you can use the Only in views for this type option. Save the changes to your content type, and the event calendar will be automatically updated. Creating events using CCK Good Eatin' Goal: Build events using the CCK module and the Date module, rather than the Event module, thereby giving additional control over the events. Additional modules needed: CCK (http://drupal.org/project/cck), Date (http://drupal.org/project/date). Basic steps Depending on your site, it may be more convenient to use CCK and the Date API to build dates. This strategy also gives you additional control over what information is included in the event and in the display. In addition, all required modules should be updated more quickly after each new Drupal release. However, you will need to carry out more initial setup for events and displays if you use this strategy. Install and activate the CCK and Date modules if you have not done so already. Open the Content Type Manager by selecting Content management and then Content types, from the Administer menu. Click Add content type to begin creating your new event type. We will call this type Event CCK to avoid conflicts with the Event module, as shown below: After you are satisfied with the information for the new content type, click Save Content Type to create the new event type. We now need to add fields to store the date and the time of the event. Click on the Add field link to begin the process. We will call the field event_time_cck and make the type a Datetime field so that we can enter both the day on which the event occurs and the time of day at which it starts, as shown in the following screenshot: Click Continue to save the new field. You will now need to select the display widget for the field. Text field with jQuery pop-up calendar is appropriate. Click Continue to complete the field definition. You can optionally modify various settings related to how the field is displayed. You should make the time Required. If you want to define end dates or times for the event, you should modify the To Date to Optional or Required. You can now create CCK-based events using the same techniques that we used to create other content—just select Create content and then Event CCK, from the main Navigation menu. Enter the information for the event, as shown in the following screenshot: When you are satisfied with the event, click Save to add the new event to the site's calendar.   Good Eatin' Goal: Display a calendar that gives more details than a block view on a page. Additional modules needed: Calendar (http://drupal.org/project/calendar), Views(http://drupal.org/project/views), Date API (http://drupal.org/ project/date). Basic steps Now that we can create events using CCK, we need to display them on the site. We will begin by creating a page where visitors can browse all of the upcoming events using a convenient calendar. Begin by installing and activating the Views and Calendar modules if you have not done so already. Note that, some versions of Calendar released prior to June 28, 2008 require you to activate both Calendar and iCal at the same time. If you experience an error when installing the Calendar module, either upgrade to the latest development module or install both modules at the same time. The easiest way to build new views using the calendar is to clone the default calendar view and customize it to meet your needs. Go to the Views Manager by selecting Site building and then Views, from the Administer menu. Drupal will display a list of all of the views that have currently been established on the site. If you scroll the list, you will see the Default Node view: calendar as shown in the following screenshot: Temporarily enable the default view by clicking on the Enable link. After the view has been activated, a new set of links will appear, labeled: Edit, Export, Clone, and Disable. Click on the Clone link to make a copy of the calendar. Drupal will allow you to change the name and description of the view. Change the name to event_calendar and then click next to edit the view. The default settings for the view are shown in the following screenshot. We will edit several settings for our purposes. The first change we need to make is to create a new Filter by clicking on the + symbol next to the Filters label. Select the Node: Type filter, as shown in the following screenshot: In most cases, you should also select the Node: published or admin filter to prevent unauthorized access to private information. Click the Add button and set the allowable types to Event CCK. The next change we will need to make is to modify the fields by selecting Node: Updated date. Click Remove to remove this field from the view. Click the + next to the Fields label to add a new field. Select Content: Event Time for the new field to be added, as shown in the following screenshot: Click Add to save the changes. You will now need to configure the display of the field. In most cases, including this one, the defaults are acceptable. So we will just click Update to continue. You will also need to update the settings for the end time (value 2), as described above. The final change we need to make to the view is in the Arguments. Select the Date:Date link in the Arguments section. Drupal will display a list of parameters that you can use to customize the arguments. We will need to change this to use our Content Event time fields, and then click Update to save the changes. Now that all of the required changes have been made, click Save to finish building the View. We can now return to the list of all views by clicking on the List link, and disable the default calendar view by selecting the Disable link for the default calendar view. Now that our view has been completely set up, we can use it to browse our events. The calendar view, which we used as a starting point, provides several methods of displaying the content as shown below: You may use any of these views, or you can add more views according to your site's needs. If you do not want to use a display type, you can delete it. If you click on the Calendar Page display type and review the Page settings, you will see that a Page is provided, which can be accessed using the path http://yoursite.com/calendar. No menu is provided. You can either add a menu link here, or use the Menu Manager if desired. If you open the calendar page, the display appears as follows: The calendar view also provides several block displays that can be activated and added to your site via the Block Manager. These blocks include a Calendar block that is similar to the display provided by the event block, and a Legend block that can be used to allow visitors to understand the information in the calendar more easily. Summary Congratulations! You have now added calendar and events to your sites. These will provide valuable ways of communicating with your customers to ensure that they keep coming back to your web site and, more importantly, to your business.  
Read more
  • 0
  • 0
  • 2052
article-image-aspnet-social-networks-making-friends-part-1
Packt
28 Oct 2009
19 min read
Save for later

ASP.NET Social Networks—Making Friends (Part 1)

Packt
28 Oct 2009
19 min read
Problem There are many aspects to building relationships in any community—real or virtual. First and foremost is initiating contact with the people whom you will eventually call your friends. We will do this in a few ways. First, we will provide a way for our users to search the site for friends who are also members. Second, we will create a form that allows you to enter your friends' email IDs and invite them directly. Third, we will create a form that allows you to import all of your contacts from Outlook. All of these methods of inviting a friend into the system would of course generate an email invite. The user would have the ability to then follow the link into the system and either sign up or log in to accept the request. The preceding screenshot shows a sample email that the user would receive in their inbox. And following is the message that would be seen: Once the user has clicked on the link in their email, he/she will be taken to a page displaying the request. Once we have a way for our users to attach friends to their profile, we need to start integrating the concept of friends into the fabric of our site. We will need a way for our users to view all of their friends. We will also need a way for our users to remove the relationships (for those users who are no longer friends!). Then we will need to add friends to our user's public profile. While this is a good first pass at integrating the concept of friends into our site, there are a couple more steps for true integration. We need to add friend request and friend confirm alerts. We also need to modify the alert system so that when users modify their profile, change their avatar, or any other alert that is triggered by users of our system, all of their friends are notified on The Filter. Once this is done we have one final topic to cover—which sort of fits in the realm of friends—the concept of Status Updates. This is a form of a micro blog. It allows users to post something about: What they are currently doing Where they are or What they are thinking about This is then added to their profile and sent out to their friends' filters. The box in the preceding screenshot is where the user can enter his/herStatus Updates. Each of these updates will also be shown on the updates view and in their filter views. This really helps to keep The Filter busy and helps people feel involved with their friends. Design Now let's talk about the design of these features. Friends This article is an attempt to throw light on the infrastructure needs and more heavily focused on the UI side for creating and managing relationships. That being said, there is always some form of groundwork that has to be in place prior to adding new features. In this case we need to add the concept of a friend prior to having the ability to create friendships. This concept is a relatively simple one as it is really only defining a relationship between two accounts. We have the account that requested the relationship and the account that accepted the relationship. This allows an account to be linked to as many other accounts as they wish. Finding friends Like in life, it is very difficult to create friends without first locating and meeting people. For that reason the various ways to locate and invite someone to be your friend is our first topic. Searching for a friend The easiest way to locate friends who might be interested in the same site that you are is to search through the existing user base. For that reason we will need to create a simple keyword search box that is accessible from any page on the site. This search feature should take a look at several fields of data pertaining to an account and return all possible users. From the search results page we should be able to initiate a friend request. Inviting a friend The next best thing to locating friends who are already members of the site is to invite people who you know out of the site. The quickest way to implement this is to allow a user to manually enter an email address or many email addresses, type a message, and then submit. This would be implemented with a simple form that generates a quick email to the recipient list. In the body of the email will be a link that allows the recipients to come in to our site. Importing friends from external sources An obvious extension of the last topic is to somehow automate the importing process of contacts from an email management tool. We will create a toolset that allows the user to export their contacts from Outlook and import them via a web form. The user should then be able to select the contacts that they want to invite. Sending an invitation With all the three of the above methods we will end up sending out an invitation email. We could simply send out an email with a link to the site. However, we need to maintain: Who has been invited Who initiated the invitation and When this occurred Then in the email, rather than just invite people in, we want to assign the user a key so that we can easily identify them on their way in. We will use a system-generated GUID to do this. In the case of inviting an existing user, we will allow him/her to log in to acknowledge the new friendship. In the case of a non-member user who was invited, we will allow him/her to create a new account. In both cases we will populate the invitation with the invited user's Account ID so that we have some history about the relationship. Adding friend alerts to the filter Once we have the framework in place for inviting and accepting friendship requests, we need to extend our existing system with alerts. These alerts should show up on existing user's Filters to show that they sent an invitation. We should also have alerts showing that a user has been invited. Once a user has accepted a friendship we should also have an alert. Interacting with your friends Now let's discuss some of the features that we need to interact with our friends. Viewing your friends Friends are only good if a user can interact with them. The first stop along this train of thought is to provide a page that allows a user to see all the friends he/she has. This is a jumping off point for a user to view the profile of friends. Also, as the concept of a user's profile grows, more data can be shown about each friend in an at-a-glance format. In addition to an all Friends page, we can add friends' views to a user's public profile so that other users can see the relationships. Managing your friends Now that we can see into all the relationships, we can finally provide the users with the ability to remove a relationship. In our initial pass this will be a permanent deletion of the relationship. Following your friends Now, we can extend the alert system so that when alerts are generated for a common user, such as updating their profile information, uploading a new photo, or any other user specific task, all the user's friends are automatically notified via their Filter. Providing status updates to your friends Somewhat related to friend-oriented relationships and The Filter is the concept of micro blogs. We need to add a way for a user to send a quick blurb about what they are doing, what they are thinking, and so on. This would also show up on the Filters of all the user's friends. This feature creates a lot of dynamic content on an end user's homepage, which keeps things interesting. Solution Now let's take a look at our solution. Implementing the database Let's look at the tables that are needed to support these new features. The Friends Table As the concept of friends is our base discussion for this article, we will immediately dive in and start creating the tables around this subject. As you have seen previously this is very straightforward table structure that simply links one account to the other. Friend Invitations This table is responsible for keeping track of who has been invited to the site, by whom, and when. It also holds the key (GUID) that is sent to the friends so that they can get back into the system under the appropriate invitation. Once a friend has accepted the relationship, their AccountID is stored here too, so that we can see how relationships were created in the past. Status Updates Status Updates allow a user to tell their friends what they are doing at that time. This is a micro blog so to speak. A micro blog allows a user to write small blurbs about anything. Examples of this are Twitter and Yammer. For more information take a look here: http://en.wikipedia.org/wiki/Micro-blogging The table needed for this is also simple. It tracks who said what, what was said, and when. Creating the Relationships Here are the relationships that we need for the tables we just discussed: Friends and Accounts via the owning account Friends and Accounts via the friends account FriendInvitations and Accounts StatusUpdates and Accounts Setting up the data access layer Let's extend the data access layer now to handle these new tables. Open your Fisharoo.dbml file and drag in these three new tables. We are not allowing LINQ to manage these relationships for us. So go ahead and remove the relationships from the surrounding tables. Once you hit Save we should have three new classes to work with! Building repositories As always, with these new tables will come new repositories. The following repositories will be created: FriendRepository FriendInvitationRepository StatusUpdateRepository In addition to the creation of the above repositories, we will also need to modify the AccountRepository. FriendRepository Most of our repositories will always follow the same design. They provide a way to get at one record, many records by a parent ID, save a record, and delete a record. This repository differs slightly from the norm when it is time to retrieve a list of friends in that it has two sides of the relationship to look at—on one side where it is the owning Account of the Friend relationship and on the other side where the relationship is owned by another account. Here is that method: public List<Friend> GetFriendsByAccountID(Int32 AccountID){ List<Friend> result = new List<Friend>(); using(FisharooDataContext dc = conn.GetContext()) { //Get my friends direct relationship IEnumerable<Friend> friends = (from f in dc.Friends where f.AccountID == AccountID && f.MyFriendsAccountID AccountID select f).Distinct(); result = friends.ToList(); //Getmy friends indirect relationship var friends2 = (from f in dc.Friends where f.MyFriendsAccountID == AccountID && f.AccountID != AccountID select new { FriendID = f.FriendID, AccountID = f.MyFriendsAccountID, MyFriendsAccountID = f.AccountID, CreateDate = f.CreateDate, Timestamp = f.Timestamp }).Distinct(); foreach (object o in friends2) { Friend friend = o as Friend; if(friend != null) result.Add(friend); } } return result;} This method queries for all friends that are owned by this account. It then queries for the reverse relationship where this account is owned by another account. Then it adds the second query to the first and returns that result. Here is the method that gets the Accounts of our Friends: public List<Account> GetFriendsAccountsByAccountID(Int32 AccountID){ List<Friend> friends = GetFriendsByAccountID(AccountID); List<int> accountIDs = new List<int>(); foreach (Friend friend in friends) { accountIDs.Add(friend.MyFriendsAccountID); } List<Account> result = new List<Account>(); using(FisharooDataContext dc = conn.GetContext()) { IEnumerable<Account> accounts = from a in dc.Accounts where accountIDs.Contains(a.AccountID) select a; result = accounts.ToList(); } return result;} This method first gathers all the friends (via the first method we discussed) and then queries for all the related accounts. It then returns the result. FriendInvitationRepository Like the other repositories this one has the standard methods. In addition to those we also need to be able to retrieve an invitation by GUID or the invitation key that was sent to the friend. public FriendInvitation GetFriendInvitationByGUID(Guid guid){ FriendInvitation friendInvitation; using(FisharooDataContext dc = conn.GetContext()) { friendInvitation = dc.FriendInvitations.Where(fi => fi.GUID == guid).FirstOrDefault(); } return friendInvitation;} This is a very straightforward query matching the GUID values. In addition to the above method we will also need a way for invitations to be cleaned up. For this reason we will also have a method named CleanUpFriendInvitations(). public void CleanUpFriendInvitationsForThisEmail(FriendInvitation friendInvitation){ using (FisharooDataContext dc = conn.GetContext()) { IEnumerable<FriendInvitation> friendInvitations = from fi in dc.FriendInvitations where fi.Email == friendInvitation.Email && fi.BecameAccountID == 0 && fi.AccountID == friendInvitation.AccountID select fi; foreach (FriendInvitation invitation in friendInvitations) { dc.FriendInvitations.DeleteOnSubmit(invitation); } dc.SubmitChanges(); }} This method is responsible for clearing out any invitations in the system that are sent from account A to account B and have not been activated (account B never did anything with the invite). Rather than checking if the invitation already exists when it is created, we will allow them to be created time and again (checking each invite during the import process of 500 contacts could really slow things down!). When account B finally accepts one of the invitations all of the others will be cleared. Also, in case account B never does anything with the invites, we will need a database process that periodically cleans out old invitations. StatusUpdateRepository Other than the norm, this repository has a method that gets topN StatusUpdates for use on the profile page. public List<StatusUpdate> GetTopNStatusUpdatesByAccountID(Int32 AccountID, Int32 Number){ List<StatusUpdate> result = new List<StatusUpdate>(); using (FisharooDataContext dc = conn.GetContext()) { IEnumerable<StatusUpdate> statusUpdates = (from su in dc.StatusUpdates where su.AccountID == AccountID orderby su.CreateDate descending select su).Take(Number); result = statusUpdates.ToList(); } return result;} This is done with a standard query with the addition of the Take() method, which translates into a TOP statement in the resulting SQL. AccountRepository With the addition of our search capabilities we will require a new method in our AccountRepository. This method will be the key for searching accounts. public List<Account> SearchAccounts(string SearchText){ List<Account> result = new List<Account>(); using (FisharooDataContext dc = conn.GetContext()) { IEnumerable<Account> accounts = from a in dc.Accounts where(a.FirstName + " " + a.LastName).Contains(SearchText) || a.Email.Contains(SearchText) || a.Username.Contains(SearchText) select a; result = accounts.ToList(); } return result;} This method currently searches through a user's first name, last name, email address, and username. This could of course be extended to their profile data and many other data points (all in good time!). Implementing the services/application layer Now that we have the repositories in place, we can begin to create the services that sit on top of those repositories. We will be creating the following services: FriendService In addition to that we will also be extending these services: AlertService PrivacyService FriendService The FriendService currently has a couple of duties. We will need it to tell us whether or not a user is a Friend, so that we can extend the PrivacyService to consider friends (recall that we currently only understand public and private settings!). In addition to that we need our FriendService to be able to handle creating Friends from a FriendInvitation. public bool IsFriend(Account account, Account accountBeingViewed){ if(account == null) return false; if(accountBeingViewed == null) return false; if(account.AccountID == accountBeingViewed.AccountID) return true; else { Friend friend = _friendRepository.GetFriendsByAccountID (accountBeingViewed.AccountID). Where(f => f.MyFriendsAccountID == account.AccountID).FirstOrDefault(); if(friend != null) return true; } return false;} This method needs to know who is making the request as well as who it is making the request about. It then verifies that both accounts are not null so that we can use them down the road and returns false if either of them are null. We then check to see if the user that is doing the viewing is the same user as is being viewed. If so we can safely return true. Then comes the fun part—currently we are using the GetFriendsByAccountID method found in the FriendRepository. We iterate through that list to see if our friend is there in the list or not. If we locate it, we return true. Otherwise the whole method has failed to locate a result and returns false. Keep in mind that this way of doing things could quickly become a major performance issue. If you are checking security around several data points frequently in the same page, this is a large query and moves a lot of data around. If someone had 500 friends this would not be acceptable. As our goal is for people to have lots of friends, we generally would not want to follow this way. Your best bet then is to create a LINQ query in the FriendsRepository to handle this logic directly only returning true or false. Now comes our CreateFriendFromFriendInvitation method, which as the name suggests, creates a friend from a friend invitation! public void CreateFriendFromFriendInvitation(Guid InvitationKey, Account InvitationTo){ //update friend invitation request FriendInvitation friendInvitation = _friendInvitationRepository. GetFriendInvitationByGUID(InvitationKey); friendInvitation.BecameAccountID = InvitationTo.AccountID; _friendInvitationRepository.SaveFriendInvitation(friendInvitation); _friendInvitationRepository.CleanUpFriendInvitationsForThisEmail(frie ndInvitation); //create friendship Friend friend = new Friend(); friend.AccountID = friendInvitation.AccountID; friend.MyFriendsAccountID = InvitationTo.AccountID; _friendRepository.SaveFriend(friend); Account InvitationFrom = _accountRepository.GetAccountByID (friendInvitation.AccountID); _alertService.AddFriendAddedAlert(InvitationFrom, InvitationTo); //TODO: MESSAGING - Add message to inbox regarding new friendship!} This method expects the InvitationKey (in the form of a system generated GUID) and the Account that is wishing to create the relationship. It then gets the FriendInvitation and updates the BecameAccountID property of the new friend. We then make a call to flush any other friend invites between these two users. Once we have everything cleaned up, we add a new alert to the system letting the account that initiated this invitation know that the invitation was accepted. AlertService The alert service is essentially a wrapper to post an alert to the user's profile on The Filter. Go through the following methods. They do not need much explanation! public void AddStatusUpdateAlert(StatusUpdate statusUpdate){ alert = new Alert(); alert.CreateDate = DateTime.Now; alert.AccountID = _userSession.CurrentUser.AccountID; alert.AlertTypeID = (int)AlertType.AlertTypes.StatusUpdate; alertMessage = "<div class="AlertHeader">" + GetProfileImage(_userSession.CurrentUser.AccountID) + GetProfileUrl(_userSession.CurrentUser.Username) + " " + statusUpdate.Status + "</div>"; alert.Message = alertMessage; SaveAlert(alert); SendAlertToFriends(alert);}public void AddFriendRequestAlert(Account FriendRequestFrom, Account FriendRequestTo, Guid requestGuid, string Message){ alert = new Alert(); alert.CreateDate = DateTime.Now; alert.AccountID = FriendRequestTo.AccountID; alertMessage = "<div class="AlertHeader">" + GetProfileImage(FriendRequestFrom.AccountID) + GetProfileUrl(FriendRequestFrom.Username) + " would like to be friends!</div>"; alertMessage += "<div class="AlertRow">"; alertMessage += FriendRequestFrom.FirstName + " " + FriendRequestFrom.LastName + " would like to be friends with you! Click this link to add this user as a friend: "; alertMessage += "<a href="" + _configuration.RootURL + "Friends/ConfirmFriendshipRequest.aspx?InvitationKey=" + requestGuid.ToString() + "">" + _configuration.RootURL + "Friends/ConfirmFriendshipRequest.aspx?InvitationKey=" + requestGuid.ToString() + "</a><HR>" + Message + "</div>"; alert.Message = alertMessage; alert.AlertTypeID = (int) AlertType.AlertTypes.FriendRequest; SaveAlert(alert);}public void AddFriendAddedAlert(Account FriendRequestFrom, Account FriendRequestTo){ alert = new Alert(); alert.CreateDate = DateTime.Now; alert.AccountID = FriendRequestFrom.AccountID; alertMessage = "<div class="AlertHeader">" + GetProfileImage(FriendRequestTo.AccountID) + GetProfileUrl(FriendRequestTo.Username) + " is now your friend!</div>"; alertMessage += "<div class="AlertRow">" + GetSendMessageUrl(FriendRequestTo.AccountID) + "</div>"; alert.Message = alertMessage; alert.AlertTypeID = (int)AlertType.AlertTypes.FriendAdded; SaveAlert(alert); alert = new Alert(); alert.CreateDate = DateTime.Now; alert.AccountID = FriendRequestTo.AccountID; alertMessage = "<div class="AlertHeader">" + GetProfileImage(FriendRequestFrom.AccountID) + GetProfileUrl(FriendRequestFrom.Username) + " is now your friend!</div>"; alertMessage += "<div class="AlertRow">" + GetSendMessageUrl(FriendRequestFrom.AccountID) + "</div>"; alert.Message = alertMessage; alert.AlertTypeID = (int)AlertType.AlertTypes.FriendAdded; SaveAlert(alert); alert = new Alert(); alert.CreateDate = DateTime.Now; alert.AlertTypeID = (int) AlertType.AlertTypes.FriendAdded; alertMessage = "<div class="AlertHeader">" + GetProfileUrl(FriendRequestFrom.Username) + " and " + GetProfileUrl(FriendRequestTo.Username) + " are now friends!</div>"; alert.Message = alertMessage; alert.AccountID = FriendRequestFrom.AccountID; SendAlertToFriends(alert); alert.AccountID = FriendRequestTo.AccountID; SendAlertToFriends(alert);} PrivacyService Now that we have a method to check if two people are friends or not, we can finally extend our PrivacyService to account for friends. Up to this point we are only interrogating whether something is marked as private or public. Friends is marked false by default! public bool ShouldShow(Int32 PrivacyFlagTypeID, Account AccountBeingViewed, Account Account, List<PrivacyFlag> Flags){ bool result; bool isFriend = _friendService.IsFriend(Account,AccountBeingViewed); //flag marked as private test if(Flags.Where(f => f.PrivacyFlagTypeID == PrivacyFlagTypeID && f.VisibilityLevelID == (int)VisibilityLevel.VisibilityLevels.Private) .FirstOrDefault() != null) result = false; //flag marked as friends only test else if (Flags.Where(f => f.PrivacyFlagTypeID == PrivacyFlagTypeID && f.VisibilityLevelID == (int)VisibilityLevel.VisibilityLevels.Friends) .FirstOrDefault() != null && isFriend) result = true; else if (Flags.Where(f => f.PrivacyFlagTypeID == PrivacyFlagTypeID && f.VisibilityLevelID == (int)VisibilityLevel.VisibilityLevels.Public) .FirstOrDefault() != null) result = true; else result = false; return result;} Summary The article started with the thought process of how we can apply the concept of Friends to our community site. We tried to figure out what we need to do to implement the concept, we then finalized our requirements, and finally we began implementing the features. In the next part of this article we will continue with the implementation process.  
Read more
  • 0
  • 0
  • 4549

article-image-installation-freenas
Packt
28 Oct 2009
28 min read
Save for later

Installation of FreeNAS

Packt
28 Oct 2009
28 min read
Downloading FreeNAS Before you can install the FreeNAS server, you will need to download the latest version from the FreeNAS website (http://www.freenas.org). Go to the download section and find the latest "LiveCD" version. The LiveCD version is what is known as an ISO image file and will have the .iso file extension. An ISO image is an exact copy of the structure and data for a CD or DVD disk. Using a CD burning program, you can create a FreeNAS bootable CD. We will look at this in more detail later on. What Hardware Do I Need? In this tutorial, we will start exploring FreeNAS, so you will need a machine on which to install the FreeNAS software. At this point in time, it doesn't have to be the final machine you are going to use as the FreeNAS server. You can use a "test" machine now and having learnt all about FreeNAS, you can build, install, and deploy a production machine (or machines) later. So, what we need now is a PC with at least 96Mb of RAM (but 128Mb or more is recommended), a bootable CD-ROM drive, a network card, one or more hard disks, and either a floppy disk drive (and a blank formatted disk) or a USB flash disk (MS-DOS formatted and empty). The hard disk will be for the data that you want to store and the floppy disk or USB flash disk will be for storing the configuration information. For the installation and initialization stages, you will also need a monitor and keyboard (but not mouse) attached to the PC. You can remove the monitor later, once FreeNAS is up and running. Warning FreeNAS boots as a LiveCD, which means that it does not use the disks on the host machine during boot up. However, when you start to configure storage on the FreeNAS server (specifically, when you format drives) all the data on the disk will be LOST. Do NOT use a machine that contains important data or an operating system that you will need afterwards. Virtualization  & VMWare The average PC runs just one operating system and inside that operating system, you would run your applications like word processing and email. There is a technology (called virtualization), which allows PCs to run more than one operating system, or to be more precise, to allow a guest virtual PC to run inside your actual PC. This virtual PC is an independent software box that can run its own OS and applications as if it were a physical computer. A virtual PC behaves exactly like a physical PC and has its own virtual CPU, RAM, hard disk, and network interface card (NIC). You can install FreeNAS on a virtual PC and FreeNAS can't tell the difference between the virtual PC and any other physical machine, also, it appears on the network just as a real PC would, running FreeNAS. There are lots of virtualization products available for Windows, Linux, and Apple OS X today. You can learn more at Wikipedia http://en.wikipedia.org/wiki/Virtualization. A very popular virtualization solution is from VMWare (http://www.vmware.com). VMWare have both commercial and freeware offerings and there are pre-configured FreeNAS images available for the VMWare range of products. This makes it an ideal environment for testing the FreeNAS server. Quick Start Guide For the Impatient If you are comfortable with burning ISO images to CDs, setting your computer's BIOS to boot from CDROM, disk partitions, and TCP/IP networking then this little guide should help you get a simple version of the FreeNAS server up and running in just a few minutes. If, however, some of these things sound daunting, then skip this section and go on to the next one where we shall go through the installation process one step at a time. For this example, we will use a USB flash disk to store the configuration information. You can use a floppy but be careful that during the boot process, the PC doesn't try to boot from the floppy before it boots from the CDROM. Burning and Booting Once you have downloaded the ISO image file from the FreeNAS website, you need to burn it to a CD. Having done that, put the CD into the PC as well as the flash disk and switch it on. Make sure that the BIOS is set to boot from CD. If it isn't, you need to enter into the BIOS and configure it to boot from CD. On many modern PCs, it is possible to select the boot device at start-up by pressing a special key (which is often either F8 or F12) to show a boot device menu. You can then select the CD as the boot device. The boot process is in four distinct parts: First, the PC will go through its POST (Power On Self Test) sequence. Here, the PC will check the amount of memory installed (which you can often see being counted on the screen) and which devices are connected (like hard drives and CDROMs). It should then start to boot from the CD. Here, FreeBSD (the underlying OS of FreeNAS) will start to boot, this is recognizable by the simple spinning wheel (made up of simple text characters like | - / and , which are animated to give the appearance of spinning). The third step is the FreeNAS boot menu. This will appear for just a few seconds and you should just let it boot normally, which is the default. The final stage is when the FreeNAS logo appears and the system will boot as FreeNAS server. You can tell when the system is fully loaded because the PC speaker will make some short but melodious beeps. To enable access to the web interface, the network of the FreeNAS server must be configured. Press the SPACE bar on the keyboard and the FreeNAS logo will disappear and a simple text menu will appear.       There are two aspects to configuring the network, first, you need to choose which network card to use and second, you need to assign it an address. If you have only one network card in your machine, then the FreeNAS server should have found it and automatically assigned it to be the LAN (Local Area Network) interface. What If My Network Card Isn't Found?This probably means that the network card in your machine isn't supported by FreeNAS or more specifically, by FreeBSD. You will need to replace the card with one supported by FreeBSD. Check the FreeBSD hardware compatibility page for more information: http://www.freebsd.org/releases/6.2R/hardware-i386.html If you see something like this: then the network has been recognized and assigned automatically by FreeNAS. The default IPv4 address for FreeNAS is 192.168.1.250, if this is good for your network, then you can just leave it unchanged. However, if you need to change it then press 2 followed by ENTER. If you want the machine to get its address from DHCP (Dynamic Host Configuration Protocol), answer yes (y) to the IPv4 DHCP question, otherwise answer no (n). If you are not using DHCP, you can now enter the desired IP address. Next, you need to enter the subnet mask. For 255.255.255.0, enter 24, for 255.255.0.0 enter 16, and for 255.0.0.0, enter 8. At this point, you can now skip the default gateway and DNS questions (by just pressing ENTER). If you do want to enter a default gateway and DNS server at this point, they will usually be the IP address of your Internet router. We won't be using IPv6 so the simplest thing to do now is just answer yes to the "Do you want to use AutoConfiguration for IPv6?" question. This will cause a small delay while FreeNAS tries (and probably fails) to get the IPv6 address but it is simpler than trying to enter the IPv6 address manually! You are now ready to access the web interface. The FreeNAS web interface can be accessed from any machine on the network with a web browser (including Windows, Linux, and OS X machines). On this client machine, type the address of the FreeNAS server with http:// in front of it into your web browser. For example: http://192.168.1.250 Configuring The first time you access the FreeNAS web interface, you will be asked for the username and password. The default username is admin and the default password is freenas. You should now be in the web interface. To configure some storage space, you need to work with "Disks". The logical order of working is that disks must be added, then formatted (if need be), then mounted. Finally, access is given to the various mounted disks by configuring different system services like CIFS and FTP.     So, to add a disk, go to Disks: Management. There is a + sign in a circle on the right-hand-side of the page (it can be easy to miss first time), click on it to add a disk. On the next page, select the disk you want to add. If you click on the drop-down menu, you should see the hard disks of the machines, the CDROM, and the USB flash disk. Dis'k Names in FreeBSD'The disk naming convention in FreeBSD is:/dev/ad0: Is the IDE/ATA Primary Master /dev/ad1 : Is the IDE/ATA Primary Slave/dev/ad2 : Is the IDE/ATA Secondary Master/dev/ad3 : Is the IDE/ATA Secondary Slave/dev/acd0 : Is the first ATA CD/DVD drive detected/dev/da0: Is the first SCSI hard drive, /dev/da1 the second and so on.USB flash disks are controlled using the SCSI driver, so they will appear as /dev/daN drives as well. Make sure ad0 is selected (which it should be by default). The rest of the page you can leave alone. Click Add to add the disk to the system. You then need to click Apply in order for the changes to take effect. You will now have a table showing you the disk you have added, including its size and a description. ApplyIn FreeNAS, the majority of steps need to be applied (which saves the configuration file to disk) by clicking the Apply button. It is normally found near the top of the page before any tables or configuration information is given. If you do not apply the changes, the interface will, on the whole, remember your changes but they will not be enacted in the system. After a reboot, unapplied changes will disappear. It is possible on some pages to make multiple operations and apply them all at the end. Next, the disk needs to be formatted. In Disks: Format, select the disk ad0 (which you just added above). Leave everything else unchanged and click Format disk. The disk will then be formatted. The low level output of the format command will be displayed in a box. It should end with Done!. Now the disk needs to be mounted. Go to Disks: Mount Point. Click on the + in the circle (which I shall refer to as the "add circle" from now on). Leave the Type as Disk and select the disk ad0 again. You need to type in a name, store is as good a name as any, but feel free to use which ever descriptive name you want to. Be DescriptiveIn setting up and configuring your FreeNAS server, you will be called upon to invent various names for mount points and share names etc. Try to be as descriptive as you can without being long winded. Temp, scratch, blob, and even zob are OK for testing, but try more meaningful names like storeage1, storage60gb or backupstorage etc. Don't use spaces in the names, instead use underline and in general, the names should be no longer than 15 characters. Although filling-in the description isn't mandatory in the web interface, it is worth using. Once you have completed the form click Add and then apply the changes. Sharing with Windows Machines Now that the disk has been added, formatted, and mounted, it is time to share it on the network and give other users the ability to read and write to it. FreeNAS supports many different types of access protocol, for this start guide, we will only look at Microsoft's CIFS protocol that primarily allows Windows machines (but also Apple OS X and Linux machines) to access the storage. In Services: CIFS/SMB, tick the enable box (in the title of the configuration data table). At this point, you can just about leave everything else as is with the exception of the workgroup name. We will be leaving the authentication method as "Anonymous" here as this is the easiest to get working and provides unrestricted read/write access to everyone. To make sure that the Windows machines are able to find the shared storage, we need to set the workgroup name, on the FreeNAS server, to be the same as the workgroup name of the Windows PC that will access the share. The default workgroup name for Windows Vista is WORKGROUP but note that the default for Window XP Home Edition was MSHOME. Now click Save and Restart. This will save the changes you have made and restart the CIFS service. Go to the Shares tab and click on add circle. Enter a name for the share. Repeating the name of the mount point is probably the safest policy, so in this case, store and also add a comment. Then click ... in the Path section. This will bring up a simple file system browser. The files you are seeing are on the FreeNAS server and NOT on your local PC. Click store and /mnt/store/ will appear in the little edit box at the click. OK it and you will be taken back to the shares page. Now /mnt/store/ has been added as the path. Leave everything else as it is and click Add and then apply the changes. So now the first hard disk of the computer is formatted, mounted, and shared to the rest of the network. Now, we will access the share from a Windows Vista machine. Testing the Share You can perform this test from any machine that supports the CIFS protocol including Windows 95/98/ME, Windows 2000/XP, Apple OS X, and Linux. Here, we are going to use Windows Vista. Open the Network and Sharing Center by clicking Network on the Start menu. When the window appears, Vista will automatically scan the network for any shared network resources. When it has finished, you will see the available machines on the network including FREENAS.     Open up the FREENAS computer and you will see store, the storage area that you configured. Double click on that and you now "inside" the FreeNAS server from within your Windows machine. Try dragging and dropping a few files in to the store area. Then try deleting them again. To access the FreeNAS server without using the Network and Sharing Center, click Start, and type freenas and then press Enter. This will bring up the shares available on the FreeNAS server directly:     Detailed Overview of Installation It is time to get your hands on a working FreeNAS server and to do that, we need to boot it up onto a PC. There are several steps to this. First, you must burn a CD of the ISO image file you have downloaded. Then, you need to boot the PC from the CD; this may involve changing your computers BIOS to make it boot from the optical drive. Then, you can configure the FreeNAS server to make some storage space available on the network. When using the LiveCD to boot FreeNAS, there are two types of storage on FreeNAS: data and configuration information. The data will be held on the hard drive of the PC, but the configuration needs to be held on a floppy disk or a USB flash disk. For this example, we will use a USB flash disk to store the configuration information. Making the FreeNAS CD To boot the PC into FreeNAS, you need a CD. The ISO image file you have downloaded contains all the information needed for the CD, but it needs to be written onto a physical CD. This process is often known as burning the CD as the laser writes to the disk by heating it and marking or scorching the surface layer. You need to use a PC with a CD-RW drive and a blank CD-R disk (I recommend using a good brand name CD-R for best results). Download the FreeNAS ISO image on to that machine. The PC with the CD writer should have some CD writing software on it (for example Roxio Easy CD or Nero). If you are familiar with the CD writing software, go ahead and burn the ISO file to the CD-R disk. If you aren't familiar with the CD writing software or it doesn't have any CD writing software, then I recommend ISO Recorder. You can download it from http://isorecorder.alexfeinman.com/isorecorder.htm.     Booting from CD Put your newly made FreeNAS CD into the CD drive of the machine on which you want to install FreeNAS, and also put the USB flash disk into a USB port. The flash disk will be used to store the configuration data. (You can also use a floppy disk. If you have both a USB flash disk and a floppy inserted, FreeNAS will save the configuration on the USB device). Now, you need to switch on the PC. When a PC starts, it goes through what is known as the Power On Self Test sequence. Here, the PC will check the amount of memory installed in the PC and find the installed hard drives. After the checks, the PC will try and boot from one of the hard drives, the CDROM, the floppy disk or even a USB flash disk. Which device the PC chooses first as its boot device can be changed by a built-in setup program. The setup program lets you modify basic system configuration settings. These settings are stored in a special battery-backed area of the computer's memory that retains the settings even when the power is switched off. During the POST sequence, there is normally a message telling you how to enter into the built-in setup program. It is normally either the DEL key or F2, on some systems it is also F10. You need to enter into the setup to check and/or change the first boot device to be the CDROM so that the computer will boot into FreeNAS. Each PC has a slightly different setup program, so you will need to search around until you find what you need. The three most popular types of setup programs (also known as BIOS Basic Input Output Program) are the Phoenix setup program, the Phoenix-Award setup program, and the AMI setup program. There are many types of BIOS setup programs and each PC manufacturer modifies the setup program for their own use. The information below is really only a "rough guide" to help you feel your way around. Your BIOS setup program may be significantly different from the examples below. The best source of information is the manual that came with your PC or your motherboard. If you don't have one, most PC manufacturers have them available for download on their websites. Phoenix BIOS If your machine has a Phoenix BIOS, then normally you need to press F2 to enter the setup program. The top of the setup program has a menu that you can navigate with the left and right arrow keys, you need to select the Boot menu.     On the Boot menu page, you can move up and down the available boot devices using the up and down arrow keys. You can expand and collapse sections with the + or signs using the ENTER key. To change the boot order, you use the + and keys. You want to make sure that the CDROM is the first device in the list. After you have changed the boot order list, you need to go to the Exit menu (by pressing the right arrow key) and select Exit Saving Changes. The PC will then reboot and after the POST, it will start to boot from the FreeNAS CD.     Phoenix-Award BIOS If your PC has a Phoenix-Award BIOS, then normally, you need to press DEL to enter the setup program. Once inside, you can the up, down, left, and right keys to navigate around the menus. Go in to Advanced BIOS Features and set the First Boot Device to be CDROM by using the + and keys. You now need to save your changes and exit. Pressing ESC will bring you back to the main menu, then select Save & Exit Setup. Often, pressing F10 will have the same effect. The PC will then reboot and if you have made the changes correctly, it will boot from the FreeNAS CD. AMI BIOS The American Megatrends, Inc (AMI) BIOS normally displays a message telling you to Hit <DEL> if you want to run setup. Once inside, it is quite different to that of the setup programs for Phoenix or Award. Here, the Tab key is used to navigate and the arrow keys are used to change values. To go from one page to the next, press the ALT+P keys. This information should also be printed at the bottom of the BIOS setup page. You need to find the variable Boot Sequence and make sure that it is set to boot from the CDROM first. First Look at FreeNAS The boot process is in 4 distinct parts. First, the PC will go through its POST (Power On Self Test) sequence. Here, the PC will check the amount of memory installed (which you can often see being counted on the screen) and which devices are connected (like hard drives and CDROMs). It should then start to boot from the CD. Here, FreeBSD (the underlying OS of FreeNAS) will start to boot, this is recognizable by the simple spinning wheel (made up of simple text characters like | - / and which are animated to give the appearance of spinning). The third step is the FreeNAS boot menu. This will appear for just five seconds and you should just let it boot normally which is the default. The final stage is when the FreeNAS logo appears and the system will boot as a FreeNAS server. You can tell when the system is fully loaded because the PC speaker will make some short but melodious beeps. Configuring the Network The majority of the configuration for FreeNAS is done via a web interface, but before you can use the web interface, the FreeNAS server needs to be configured for your network. This is done via a simple text menu system using the keyboard and monitor attached to the PC with FreeNAS running on it. You probably only need to do this once, and after that this new network information will be saved on the USB flash disk (or floppy disk) and the server will boot into this configuration every time. If you press the SPACE bar on FreeNAS machine, the FreeNAS logo will disappear and a simple menu will appear.     Here, you have a number of options including options to reboot or power off the system. The first two options are about configuring the network and they reflect the two parts to configuring the network, first you need to choose which network card to use (option 1) and second you need to assign it an address (option 2). If you have only one network card in your machine then the FreeNAS server should have found it and automatically assigned it to be the LAN (Local Area Network) interface. What If My Network Card Isn't Found?This probably means that the network card in your machine isn't supported by FreeNAS or more specifically by FreeBSD. You will need to replace the card with one supported by FreeBSD. Check the FreeBSD hardware compatibility page for more information: http://www.freebsd.org/releases/6.2R/hardware-i386.html If you see something like the following screenshot:     then the network has been recognised and assigned automatically by FreeNAS. What is a LAN IP Address? IP stands for Internet Protocol and it is the basic low level language that computers use to talk to each other on the Internet. It is also used on private networks (in the office or at home) to connect different PCs and even printers to each other. An IPv4 address is made up of 4 sets of number (0 to 255) and is expressed in what is known as dot notation (meaning that each number has a dot between it). So 192.168.1.250 is an IP address, it also happens to be the default IP address for the FreeNAS server. Like email, the postal service and telephone, each destination (email account, mailbox or handset) needs a unique way of being identified. This is what IP addresses do; they allow each piece of equipment on the network to have a unique identifier so that messages can be addressed to the right place on the network. Pronouncing IP AddressesIf you need to speak to someone about an IP address, the simplest way is to speak about each digit separately, so 192.168.1.250 isn't "one hundred and ninety two dot" but rather "one nine two dot one six eight dot one dot two five zero". There are two ways in which you can obtain an IP address for the FreeNAS server. The first is to have the address assigned automatically via the DHCP service (Dynamic Host Configuration Protocol), and the second is to assign it manually. What is DHCP?The Dynamic Host Configuration Protocol (DHCP) automates the assignment of IP addresses and other IP parameters (like subnet masks and default gateway). A computer that needs an IP address will send a request to the DHCP server and the server will reply with an IP address from a pool of addresses that have been set aside for this purpose. A DHCP server can be a PC or server (running Windows, OS X or Linux) as well as small devices like modern DSL modems and firewalls. The advantage of the DHCP method is that the IP address assignment, all happens in the background and you don't need to worry about setting it yourself. The disadvantages are that first you need to have an already configured and running DHCP server on your network; and second, DHCP assigns addresses from a pool of available addresses. This means that every time the FreeNAS server boots, it is not guaranteed to have the same address as it had previously. This isn't a problem when using the CIFS protocol, however, for accessing the web interface or using protocols like FTP, it is desirable to have a stable IP address to refer to. However, for testing the FreeNAS server and learning about how it works using a DHCP assigned address could be acceptable for now. It is actually possible to assign fixed, permanent IP address to certain pieces of hardware, including a FreeNAS server over DHCP, but that requires extra advanced configuration changes in the DHCP server that cannot be covered in this tutorial. So opting for the manual IP address, you now need to obtain two pieces of information. The first is the actual IP address for the FreeNAS and the second is what is known as the subnet mask. The subnet mask will also be expressed in the dot notation and is normally something like 255.255.255.0. If you are in an office environment, you need to speak to the network administrator and he/she will be able to give you the information you need. If you are administering your own network, you need to choose an IP that isn't currently allocated to any other machine on your network (and also, isn't part of the address pool of any DHCP server on your network). Having obtained the IP address and subnet mask, you can now configure the FreeNAS server for your network. Select option 2 on the console menu. If you have chosen to have DHCP assign the address, answer yes (y) to the first question about using DHCP for IPv4. Otherwise answer no (n). If you are setting the address manually, you can now enter the address in dot notation, i.e. 192.168.1.240. Next, comes the subnet mask. If your subnet mask is 255.255.255.0: enter 24, for 255.255.0.0: enter 16, and for 255.0.0.0: enter 8. At this point, you can now skip the default gateway and DNS questions (by just pressing ENTER). We won't be using IPv6 so the simplest thing to do now is just answer yes to the "Do you want to use AutoConfiguration for IPv6?" question. This will cause a small delay while FreeNAS tries (and probably fails) to get the IPv6 address but it is simpler than trying to enter the IPv6 address manually! After you have successful set the IP address, there will be a small message on the screen inviting you to access the web interface by opening the listed URL in your web browser. If you have used DHCP, note down the URL listed. If you set the IP address manually, check that the URL listed is the same as the IP address you set with [http:// http://] in front of it. You are now ready to access the web interface. What is IPv4 and IPv6?The Internet Protocol has been around since the mid 1980's and when it was designed, the popularity of the Internet was not envisaged. The number of computers connected to the Internet is quickly growing beyond the addressing capabilities of the original protocol. As an answer to this, a new version of the IP protocol has been designed and has been given the name IP version 6 or IPv6 for short and the older version has taken the name IP version 4 or IPv4 for short. FreeNAS supports both versions of the Internet Protocol. In this tutorial, we will concentrate just on IPv4 as it still remains the most popular of the two protocols. Basic Configuration With your FreeNAS server now being up and running, it is time to access the web interface. Open a web browser on a computer on the same network as the FreeNAS server. Enter in the URL of the FreeNAS server. This should be the same as the IP address of the server with [http:// http://] in the front. The default URL is http://192.168.1.250     The first time you access the FreeNAS web interface, you will be asked for the username and password. The default username is admin and the default password is freenas. FreeNAS Web Interface You should now have the web interface in your browser. The interface is split into two main sections. Down the left-hand-side are the menus, and the right-hand-side contains the pages for configuration. The menus are split into various sections: System, Interfaces, Disks, Services, Access, Status, Diagnostics, and Advanced.     When talking about a particular menu item, we shall use the notation Subsection: Menu Item to help you find the right menu option easily. So, the Management option, which is in the Disks subsection, will be referred to as Disks: Management. System This section is for system level configuration and operations, here for example you can change the username and password, backup and restore the configuration data, and shutdown or reboot the server. Interfaces Here, you can configure the network of the FreeNAS server much like you did via the console menu. You can change the network card that is used for the web interface and assign permanent or automatic IP addresses. Be careful when you change things here as some changes won't take effect until you reboot. If you have changed any of the addressing, you will need to access the web interface with the IP address. Disks This section of the menu is for administering the disks on the server. Here, you can set up disk redundancy (RAID), control encryption, format disks, and mount the disks on the server. Services The various access protocols like CIFS, NFS, and FTP are controlled from here. Each service is administered individually and by default NONE of the services are enabled, so before you can access files stored on the FreeNAS server, you need to enable at least one of these services. Access Most of the services offered by FreeNAS use some form of list of users to control who has access and who does not. This section is for defining these users and the groups they belong to as well as connecting the FreeNAS server to other directory services. Status The status menu has several reporting tools for you to see the current state of your FreeNAS server including a general overview, memory usage, disk usage, and network usage. You can also configure emails to be sent periodically about the status of the server. Diagnostics The diagnostics menu contains different tools to help diagnose any problem with the FreeNAS server, including logs of all the important services and diagnostic information from the hard disks and other system modules. Advanced The advanced section provides some simple tools for executing commands at the operating system level and should not be used by those unfamiliar with FreeBSD.    
Read more
  • 0
  • 0
  • 7275

article-image-enabling-spring-faces-support
Packt
28 Oct 2009
9 min read
Save for later

Enabling Spring Faces support

Packt
28 Oct 2009
9 min read
The main focus of the Spring Web Flow Framework is to deliver the infrastructure to describe the page flow of a web application. The flow itself is a very important element of a web application, because it describes its structure, particularly the structure of the implemented business use cases. But besides the flow which is only in the background, the user of your application is interested in the Graphical User Interface (GUI). Therefore, we need a solution of how to provide a rich user interface to the users. One framework which offers components is JavaServer Faces (JSF). With the release of Spring Web Flow 2, an integration module to connect these two technologies, called Spring Faces has been introduced. This article is no introduction to the JavaServer Faces technology. It is only a description about the integration of Spring Web Flow 2 with JSF. If you have never previously worked with JSF, please refer to the JSF reference to gain knowledge about the essential concepts of JavaServer Faces. JavaServer Faces (JSF)—a brief introductionThe JavaServer Faces (JSF) technology is a web application framework with the goal to make the development of user interfaces for a web application (based on Java EE) easier. JSF uses a component-based approach with an own lifecycle model, instead of a request-driven approach used by traditional MVC web frameworks. The version 1.0 of JSF is specified inside JSR (Java Specification Request) 127 (http://jcp.org/en/jsr/detail?id=127). To use the Spring Faces module, you have to add some configuration to your application. The diagram below depicts the single configuration blocks. These blocks are described in this article. The first step in the configuration is to configure the JSF framework itself. That is done in the deployment descriptor of the web application—web.xml. The servlet has to be loaded at the startup of the application. This is done with the <load-on-startup>1</load-on-startup> element. <!-- Initialization of the JSF implementation. The Servlet is not used at runtime --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> For the work with the JavaServer Faces, there are two important classes. These are the javax.faces.webapp.FacesServlet and the javax.faces.context.FacesContext classes.You can think of FacesServlet as the core base of each JSF application. Sometimes that servlet is called an infrastructure servlet. It is important to mention that each JSF application in one web container has its own instance of the FacesServlet class. This means that an infrastructure servlet cannot be shared between many web applications on the same JEE web container.FacesContext is the data container which encapsulates all information that is necessary around the current request.For the usage of Spring Faces, it is important to know that FacesServlet is only used to instantiate the framework. A further usage inside Spring Faces is not done. To be able to use the components from Spring Faces library, it's required to use Facelets instead of JSP. Therefore, we have to configure that mechanism. If you are interested in reading more about the Facelets technology, visit the Facelets homepage from java.net with the following URL: https://facelets.dev.java.net. A good introduction inside the Facelets technology is the http://www.ibm.com/developerworks/java/library/j-facelets/ article, too. The configuration process is done inside the deployment descriptor of your web application—web.xml. The following sample shows the configuration inside the mentioned file. <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value></context-param> As you can see in the above code, the configuration parameter is done with a context parameter. The name of the parameter is javax.faces.DEFAULT_SUFFIX. The value for that context parameter is .xhtml. Inside the Facelets technology To present the separate views inside a JSF context, you need a specific view handler technology. One of those technologies is the well-known JavaServer Pages (JSP) technology. Facelets are an alternative for the JSP inside the JSF context. Instead, to define the views in JSP syntax, you will use XML. The pages are created using XHTML. The Facelets technology offers the following features: A template mechanism, similar to the mechanism which is known from the Tiles framework The composition of components based on other components Custom logic tags Expression functions With the Facelets technology, it's possible to use HTML for your pages. Therefore, it's easy to create the pages and view them directly in a browser, because you don't need an application server between the processes of designing a page The possibility to create libraries of your components The following sample shows a sample XHTML page which uses the component aliasing mechanism of the Facelets technology. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html > <body> <form jsfc="h:form"> <span jsfc="h:outputText" value="Welcome to our page: #{user.name}" disabled="#{empty user}" /> <input type="text" jsfc="h:inputText" value="#{bean.theProperty}" /> <input type="submit" jsfc="h:commandButton" value="OK" action="#{bean.doIt}" /> </form> </body></html> The sample code snippet above uses the mentioned expression language (for example, the #{user.name} expression accesses the name property from the user instance) of the JSF technology to access the data. What is component aliasingOne of the mentioned features of the Facelets technology is that it is possible to view a page directly in a browser without that the page is running inside a JEE container environment. This is possible through the component aliasing feature. With this feature, you can use normal HTML elements, for example an input element. Additionally, you can refer to the component which is used behind the scenes with the jsfc attribute. An example for that is <input type="text" jsfc="h:inputText" value="#{bean.theProperty}" /> . If you open this inside a browser, the normal input element is used. If you use it inside your application, the h:inputText element of the component library is used     The ResourceServlet One main part of the JSF framework are the components for the GUI. These components often consist of many files besides the class files. If you use many of these components, the problem of handling these files arises. To solve this problem, the files such as JavaScript and CSS (Cascading Style Sheets) can be delivered inside the JAR archive of the component. If you deliver the file inside the JAR file, you can organize the components in one file and therefore it is easier for the deployment and maintenance of your component library. Regardless of the framework you use, the result is HTML. The resources inside the HTML pages are required as URLs. For that, we need a way to access these resources inside the archive with the HTTP protocol. To solve that problem, there is a servlet with the name ResourceServlet (package org.springframework.js.resource). The servlet can deliver the following resources: Resources which are available inside the web application (for example, CSS files) Resources inside a JAR archive The configuration of the servlet inside web.xml is shown below: <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class> <load-on-startup>0</load-on-startup></servlet> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/resources/*</url-pattern></servlet-mapping> It is important that you use the correct url-pattern inside servlet-mapping. As you can see in the sample above, you have to use /resources/*. If a component does not work (from the Spring Faces components), first check if you have the correct mapping for the servlet. All resources in the context of Spring Faces should be retrieved through this Servlet. The base URL is /resources. Internals of the ResourceServlet ResourceServlet can only be accessed via a GET request. The ResourceServlet servlet implements only the GET method. Therefore, it's not possible to serve POST requests. Before we describe the separate steps, we want to show you the complete process, illustrated in the diagram below: For a better understanding, we choose an example for the explanation of the mechanism which is shown in the previous diagram. Let us assume that we have registered the ResourcesServlet as mentioned before and we request a resource by the following sample URL: http://localhost:8080/ flowtrac-web-jsf/resources/css/test1.css. How to request more than one resource with one requestFirst, you can specify the appended parameter. The value of the parameter is the path to the resource you want to retrieve. An example for that is the following URL: http://localhost:8080/ flowtracweb-jsf/resources/css/test1.css?appended=/css/test2.css. If you want to specify more than one resource, you can use the delimiter comma inside the value for the appended parameter. A simple example for that mechanism is the following URL: http://localhost:8080/ flowtrac-web-jsf/resources/css/test1.css?appended=/css/test2.css, http://localhost:8080/flowtrac-web-jsf/resources/css/test1.css?appended=/css/test3.css. Additionally, it is possible to use the comma delimiter inside the PathInfo. For example: http://localhost:8080/flowtrac-web-jsf/resources/css/test1.css,/css/test2.css. It is important to mention that if one resource of the requested resources is not available, none of the requested resources is delivered. This mechanism can be used to deliver more than one CSS in one request. From the view of development, it can make sense to modularize your CSS files to get more maintainable CSS files. With that concept, the client gets one CSS, instead of many CSS files. From the view of performance optimization, it is better to have as few requests for rendering a page as possible. Therefore, it makes sense to combine the CSS files of a page. Internally, the files are written in the same sequence as they are requested. To understand how a resource is addressed, we separate the sample URL into the specific parts. The example URL is a URL on a local servlet container which has an HTTP connector at port 8080. See the following diagram for the mentioned separation: The table below describes the five sections of the URL that are shown in the previous diagram:
Read more
  • 0
  • 1
  • 26934
article-image-installing-alfresco-software-development-kit-sdk
Packt
28 Oct 2009
6 min read
Save for later

Installing Alfresco Software Development Kit (SDK)

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

article-image-troubleshooting-freenas-server
Packt
28 Oct 2009
9 min read
Save for later

Troubleshooting FreeNAS server

Packt
28 Oct 2009
9 min read
Where to Look for Log Information The first place to head whenever you have a configuration problem with FreeNAS is to the related configuration section and check that it is configured as expected. If, having double checked the settings, the problem persists, the next port of call is the log and information files in the Diagnostics: section of the web interface. Keep Diagnostics Section ExpandedBy default, the menu tree in the Diagnostics section of the web interface is collapsed, meaning the menu items aren't visible. To see the menu items, you need to click the word Diagnostics and the tree will expand. During initial setup and if you are doing lots of troubleshooting, you can save yourself a click by having the Diagnostics section permanently expanded. To set this option, go to System: Advanced and click on the Navigation - Keep diagnostics in navigation expanded tick box. The Diagnostics sections has five sections, the first two are logs and information pages about the status of the FreeNAS server. The other three are networking diagnostic tools and information. Diagnostics: Logs This section collates all the different log files that are generated by the FreeNAS server into one convenient place. There are several tabs, one for each different service to log file type. Some of the information can be very technical, especially in the System tab. However, with some key information they can become more readable. The tabs are as follows: Tab Meaning System When FreeBSD (the underlying OS of FreeNAS) boots, various log entries are recorded here about the hardware of the server and various messages about the boot process. FTP This shows the activity on the FTP server including successful logins and failed logins. RSYNC The log information for the RSYNC server is divided into three sections: Server, Client, and Local. Depending on which type of RSYNC operation you are interested, click the appropriate tab. SSHD Here you will find log entries from the SSH server including some limited startup information and records of logins and failed login attempts. SMARTD This tab logs the output of the S.M.A.R.T daemon. Daemon Any other minor system service like the built-in HTTP server, the Apple Filing Protocol server and Windows networking server (Samab) will log information to this page. UPnP The log information from the FreeNAS UPnP server called "MediaTomb" is displayed here. The logging can be quite verbose so careful attention is needed when reading it. Don't be distracted by entires such as "INFO: Config: option not found:" as this is just the server logging that it will be using a default value for that particular attribute. Settings The settings tab allows you to change how the log information is displayed including the sort order and the number of entries shown. What is a Daemon?In UNIX speak, a Daemon is a system service. It is a program that runs in the background performing certain tasks. The Daemons in FreeNAS don't work with the users in an interactive mode (via the monitor, mouse, and keyboard) and as such need a place to log the results (or problems)of their actives. The FreeNAS Daemons are launched automatically by FreeBSD when it boots and some are dependent on being enabled in the web interface. Understanding Diagnostics Logs: System The most complicated of all the log pages is the System log page. Here, FreeBSD logs information about the system, its hardware, and the startup process. At first, this page can seem intimidating but with a little help, this page can be very helpful particularly in tracking down hardware or driver related problems. 50 Log Entries Might Not be EnoughThe default number of log entries shown on the Diagnostics: Logs page is 50. For most situations, this will be sufficient but there can be times when it is not enough. For example in the Diagnostics: Logs: System tab, the total number of log entries made during the boot up process is more than 50. If you want to see how much system memory has been recognized by FreeBSD, you won't find it within the standard 50 entries. The solution is to increase the Number of log entries to show parameter on the Diagnostics: Logs: Setting tab. The best way to learn to read the Diagnostics: Logs: System page is by example, below are several different log entry examples including logs about the CPU, memory, disks, and disk controllers: kernel: FreeBSD 6.2-RELEASE-p11 #0: Wed Mar 12 18:17:49 CET 2008 This first entry shows the heritage of the FreeNAS server. It is based on FreeBSD and in this particular case, we see that this version of FreeNAS is using FreeBSD 6.2. There are plans (which may have already become reality) to use FreeBSD version 7.0 as the base for FreeNAS. kernel: CPU: Intel(R) Xeon(TM) CPU 1.70GHz (1680.52-MHz 686-class CPU) Here, the type of CPU that was detected by the FreeBSD is displayed. In this case, it is an Intel Xeon CPU running at 1.7GHz. kernel: FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs If your system has more than one CPU or is a dual core machine then you will see an entry in the log file (like the one above) recognizing the second CPU. If your machine has Hyper-threading technology, then the second logical processor will be reported like this: Logical CPUs per core:2 Apr 1 11:06:00 kernel: real memory = 268435456 (256 MB)Apr 1 11:06:00 kernel: avail memory = 252907520 (241 MB) These log entries show how much memory the system has detected. The difference in size between real memory and available memory is the difference between the amount of RAM physically installed in the computer and the amount of memory left over after the FreeBSD kernel is loaded. kernel: atapci0: <Intel PIIX4 UDMA33 controller> port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0x1050-0x105f at device 7.1 on pci0 kernel: ata0: <ATA channel 0> on atapci0 kernel: ata1: <ATA channel 1> on atapci0 For disks to work on your FreeNAS server, a disk controller is needed and it will be either a standard ATA/IDE controller, a SATA controller or a SCSI controller. Above are the log entries for a standard ATA controller built into the motherboard. You can see that it is an Intel controller and that two channels have been seen (the primary and the secondary). kernel: atapci1: <SiS 181 SATA150 controller> irq 17 at device 5.0 on pci0kernel: ata2: <ATA channel 0> on atapci1kernel: ata3: <ATA channel 1> on atapci1 Like the ATA controller listed a moment ago, SATA controllers are all recognized at boot up. Here is a SiS 181 SATA 150 controller with two channels. They are listed as devices ata2 and ata3 as ata0 and ata1 are used by the standard ATA/IDE controller. kernel: mpt0: <LSILogic 1030 Ultra4 Adapter> irq 17 at device 16.0 on pci0 Like IDE and SATA controllers, all recognized SCSI drivers are listed in the boot up system log. Here, the controller is an LSILogic 1030 Ultra4. kernel: ad0: 476940MB <WDC WD5000AAJB-00YRA0 12.01C02> at ata0-master UDMA100kernel: ad4: 476940MB <Seagate ST3500320AS SD04> at ata2-master SATA150 Once the disk controllers are recognized by the system, FreeBSD can search to see which disks are attached. Above is an example of a Western Digital 500GB hard drive using the standard ATA100 interface at 100MB/s. There is also a 500GB Seagate drive connected using the SATA interface. acd0: CDROM <TOSHIBA CD-ROM XM-7002B/1005> at ata1 as master UDMA33 When the CDROM (which is normally attached to an ATA/IDE controller) is recognized, it will look like the above. kernel: da0 at ahd0 bus 0 target 0 lun 0kernel: da0: <MAXTOR ATLAS10K4_73WLS DFL0> Fixed Direct Access SCSI-3 devicekernel: da0: 320.000MB/s transfers (160.000MHz, offset 127, 16bit), Tagged Queueing Enabledkernel: da0: 70149MB (143666192 512 byte sectors: 255H 63S/T 8942C) SCSI addressing is a little more complicated than that of ATA/IDE. In SCSI land, you have a controller, a channel (bus), a disk (target), and the Logical Unit Number (LUN). The example above shows that a disk (which has been assigned the device name da0) is found on the controller ahd0 on bus 0, as target 0 with the LUN 0. SCSI controllers can have multiple buses and multiple targets. Further down, you can see that the disk is a MAXTOR 73GB SCSI-3 disk. kernel: da0 at umass-sim0 bus 0 target 0 lun 0kernel: da0: <Verbatim Store 'n' Go 1.30> Removable Direct Access SCSI-2 devicekernel: da0: 40.000MB/s transferskernel: da0: 963MB (1974271 512 byte sectors: 64H 32S/T 963C) If you are using a USB flash disk for storing the configuration information, it will most likely appear in the log file as a type of SCSI disk. The above example shows a 1GB Verbatim Store 'n' Go disk. kernel: lnc0: <PCNet/PCI Ethernet adapter> irq 18 at device 17.0 on pci0kernel: lnc0: Ethernet address: 00:0c:29:a5:9a:28 Another important device that needs to work correctly on your system is the network interface card. Like disk controllers and disks, it will be logged in the log file when FreeBSD recognizes it. Above is an example of an AMD Lance/PCNet-based Ethernet adapter. Each Ethernet card has a unique address know as the Ethernet address or the MAC address. It is made up of 6 numbers specified using a colon notation. Once found, FreeBSD queries the card to find its MAC address and logs the result. In the above example, it is "00:0c:29:a5:9a:28". Converting between Device Names and the Real World In the SCSI example above, the SCSI controller listed is ahd0. The trick to understanding these log entries better is to know how to interpret the device name ahd0. First of all ahd0 means it is a device using the ahd driver and it is the first one in the system (with numbering starting from 0). So what is a ahd? The first place to look is further up in the log file. There should be an entry like: kernel: ahd0: <Adaptec 39320 Ultra320 SCSI adapter> irq 11 at device 1.0 on pci2 This shows that the particular device is an Adaptec 39320 SCSI 3 controller. You can also find out more about the the ahd driver (and all FreeBSD drivers) at: http://www.freebsd.org/releases/6.2R/hardware-i386.html Search for ahd and you will find which controllers this driver supports (in this case, they are all controllers from Adaptec. If you click on the link provided, you will be taken to a specific help page about this driver. When FreeNAS moves to FreeBSD 7, then the relevant web page will be: http://www.freebsd.org/releases/7.0R/hardware.html.
Read more
  • 0
  • 0
  • 13837
Modal Close icon
Modal Close icon