Getting Started with Lean Software Development
By Curt Hibbs , Steve Jewett and Mike Sullivan
20,865 Downloads · Refcard 93 of 187 (see them all)
Download
FREE PDF
The Essential Lean Development Cheat Sheet
Getting Started with Lean Software Development
About Lean Software Development
Lean Software Development is an outgrowth of the larger Lean movement that includes areas such as manufacturing, supply chain management, product development, and back-office operations. Its goal is the same: deliver value to the customer more quickly by eliminating waste and improving quality. Though software development differs from the manufacturing context in which Lean was born, it draws on many of the same principles.
Seven Principles of Lean Software Development
Lean Software Development embodies seven principles, originally described in the book Implementing Lean Software Development: From Concept to Cash1, by Mary and Tom Poppendieck. Each of these seven principles contributes to the “leaning out” of a software development process.
Eliminate Waste
Waste is anything that does not contribute value to the final product, including inefficient processes, unnecessary documentation, and features that won't be used. Eliminating waste is the guiding principle in Lean Software Development.
Build Quality In
Building quality into a product means preventing defects, rather than using post-implementation integration and testing to detect them after the fact.
Create Knowledge
The knowledge necessary to develop a project, including requirements, architecture, and technologies, is seldom known or understood completely at project startup. Creating knowledge and recording it over the course of the project ensures the final product is in line with customer expectations.
Defer Commitment
Making irreversible decisions at the last reasonable moment allows time for the creation of more knowledge, which results in better decisions. Deferring commitment is positive procrastination.
Deliver Fast
Delivering fast puts the product in front of the customer quickly so they can provide feedback. Fast delivery is accomplished using short iterations, which produce software in small increments by focusing on a limited number of the highest priority requirements.
Respect People
Respecting people means giving the development team's most important resource, its members, freedom to find the best way to accomplish a task, recognizing their efforts, and standing by them when those efforts are unsuccessful.
Optimize the Whole
Optimizing the whole development process generates better results than optimizing local processes in isolation, which is usually done the expense of other local processes.
Lean vs. Agile
Comparing Lean and Agile software development reveals they share many characteristics, including the quick delivery of value to the customer, but they differ in two significant ways: scope and focus. The narrow scope of Agile addresses the development of software and focuses on adaptability to deliver quickly. Lean looks at the bigger picture, the context in which development occurs, and delivers value quickly by focusing on the elimination of waste. As it turns out, they are complementary, and real world processes often draw from both.
GETTING STARTED
Newcomers to Lean Software Development sometimes have trouble implementing a Lean process. The Lean principles don't describe an “out-of-the-box” solution, so one approach is to start with an Agile methodology. However, a number of methodologies exist, and choosing the right one can be difficult.
One Step at a Time
All is not lost. What follows is a set of inter-related practices organized in a step-by-step fashion to allow projects to implement Lean Software Development one step at a time.
The following practices can stand-alone, and implementing any of them will have a positive effect on productivity. Lean Software Development relies on prioritization, so the practices are prioritized to generate the highest return on investment. While implementing any one practice will help lean out a process, doing them in order will return the most “bang for the buck.”
The list of six practices is preceded by two prerequisites, or “zero practices”, every software project should be doing, whether Lean, Agile or something more traditional. If your project doesn't do these things, this is the best place to start.
ZERO PRACTICES
Source Code Management and Scripted Builds are prerequisites for other practices outlined here. They are referred to as zero practices because they need to be in place before taking the first step toward Lean Software Development.
Source Code Management
Source code management (SCM) is a shared repository for all artifacts needed to build the project from scratch, including source code, build scripts, and tests. SCM maintains the latest source code so developers and build systems have up-to-date code.

Figure 1: Centralized Repository
Source code management is the first practice described because it is the foundation for a practical development environment, and it should be implemented before going any further.
- Select an appropriate SCM system. Subversion is a popular open source option. Git is a newer distributed SCM system useful for large projects and distributed teams.
- Put everything needed to build the product from scratch into the SCM system so critical knowledge isn't held only by specific individuals.
Scripted Builds
Scripted builds automate a build process by executing a set of commands (a script) that creates the final product from the source code stored in SCM. Scripts may be simple command files, make files, or complex builds within a tool such as Maven or Ant.
Scripted builds eliminate the potential errors of manual builds by executing the same way each time. They complete the basic development cycle of making changes, updating the SCM repository, and rebuilding to verify there are no errors. Select an appropriate build tool for your project. Integrated development environments like Visual Studio or Eclipse have build managers or integrate with 3rd party build managers. Create a script that builds the product from scratch, starting with source code from SCM.

Figure 2: Zero Practices
Lean Principles
- Create Knowledge: SCM consolidates project knowledge in a single place.
- Eliminate Waste: Manual work is eliminated by automating builds.
- Build Quality In: Automating builds eliminates a source of errors.
DAILY STANDUP
Daily standup meetings allow each team member to provide status and point out problems or issues. The meetings are short and not intended to resolve problems, rather they serve to make all team members aware of the state of the development effort.
Borrowing from the Scrum methodology, standups are conducted by having each member of the team answer three questions:
What did I do yesterday?
What will I do today?
What problems do I have?
Effective daily standups result from adhering to several simple rules:
- Require all team members to attend. Anyone who cannot attend must submit their status via a proxy (another team member, email, etc.).
- Keep the meeting short, typically less than 15 minutes. Time-boxing the meeting keeps the focus on the three questions.
- Hold the meeting in the same place at the same time, everytime.
- Avoid long discussions. Issues needing further discussion are addressed outside the meeting so only the required team members are impacted.

The Japanese word tsune roughly translated means “daily habits”. It refers to things such as taking a shower that are so ingrained into a daily routine that skipping them leaves one feeling that something is missing2. Make the daily standup part of the team's tsune so that a day without a standup feels incomplete.
Lean Principles
- Respect People: Standups foster a team-oriented attitude; team members know what other members are doing and can get or give help as needed to move the project forward.
- Create Knowledge: Sharing information regularly creates group knowledge from individual knowledge.
AUTOMATED TESTING
Automated testing is the execution of tests using a single command. A test framework injects pre-defined inputs, validates outputs against expected results, and reports the pass/fail status of the tests without the intervention of a human tester. Automated testing ensures tests are run the same way every time and are not subject to the errors and variations introduced by testers.
While automated testing can be applied to all types of testing from unit and integration tests to user acceptance and performance/load tests, unit and integration testing is the best place to start.
- Identify an appropriate test framework for the language in use. JUnit (for Java) and NUnit (for Microsoft .NET languages) are common frameworks.
- Require all new code modules to have a unit test suite before being included in the build.
- Retrofit unit test suites to existing legacy code only when the code is modified (writing unit tests for code which is already written and functional usually is not cost effective).
- Develop integration tests by combining code modules and testing the modules together.
- Use stubs and mock objects to stand in for code which has not yet been developed.

Developing automated tests alongside production code may be a paradigm shift for many developers. One way to help developers adjust is to define testing standards calling out both what to test and how to do it. Adherence to the standards will create a culture where automated tests are the norm and will pay off in higher quality software.

Figure 3: Automated Testing
Test Execution
Each developer runs unit tests on individual code modules prior to adding them to the source code repository, ensuring all code within the repository is functional. An automated build runs both unit and integration tests to ensure changes do not introduce errors. The next practice, continuous integration, will make use of the build scripts and test suites to test the entire system automatically each time changes are checked into the repository.
Lean Principles
- Build Quality In: Automated tests executed regularly and in a consistent manner prevent defects.
- Eliminate Waste: Defects detected early are easier to correct and don't propagate.
- Create Knowledge: Tests are an effective way to document how the code functions.
CONTINUOUS INTEGRATION
Continuous integration (CI) is the frequent integration of small changes during implementation. It seeks to reduce, or even eliminate, the long, drawn-out integration phase traditionally following implementation. Integrating small changes doesn't just spread the effort out over the whole cycle, it reduces the amount of integration time because small changes are easier to integrate and aid debugging by isolating defects to small areas of code.
CI systems use a source code repository, scripted builds, and automated tests to retrieve source code, build software, execute tests, and report results each time a change is made.
- Use a dedicated build machine to host the CI system. Refer to the Continuous Integration: Servers and Tools Refcard (#87) for details on setting up a CI system.
- Check code changes into the repository a minimum of once a day (per developer); once an hour or more is even better.
- Immediately address any failures in the build. Fixing the build takes precedence over further implementation.

While the use of a dedicated computer, or build machine, to host the CI system may seem obvious for a large project, it provides advantages on small projects as well:
- Dedicated machines don't compete for resources, so builds are quicker and the results get back to the developers sooner.
- Dedicated machines have a stable, well-known configuration. Builds don't fail because a new version of a library was loaded or the runtime environment was changed.
A CI system can also check coding standards, analyze code coverage, create documentation, create deployment packages, and deploy the packages. Anything that can be automated can be included in a CI system.

Lean Principles
- Build Quality In: Continuous build and test ensures code is always functional.
- Eliminate Waste: Frequent, small integrations are more efficient than an extended integration phase.
LESS CODE
Less code is not about writing less software, it's about implementing required functionality with a minimum amount of code. Large code bases mean more implementation, integration, and debugging time, as well as higher long term maintenance costs. All of these are non-value added work (i.e., waste) when the code base contains unneeded or inefficient code.
All aspects of software development can affect the code base size. Requirements analysis resulting in features with little likelihood of use and overly generic, all-encompassing designs generate extra code. Scope creep and unnecessary features increase the amount of code. Even testing can generate unnecessary code if the code under test is itself unnecessary.
Minimizing code base size requires two actions: identify and eliminate unnecessary code, and write efficient code. Minimizing code base size is not unlike a fitness program: diet to eliminate the excess, and exercise to shape up what's left.
Eliminate Unnecessary Code
Eliminating unnecessary code means identifying the code, or the forces that create it, and removing it.
- Adopt a fierce, minimalist approach. Every bit of code added to the code base must be justifiable. Remove excessive requirements, simplify designs, and eliminate scope creep.
- Reuse code and employ libraries to reduce the amount of new code that must be written.
- Prioritize requirements so developers implement important features first. As customers adjust the priorities over the course of development, they drive development of only useful features; unused features never get implemented.
- Develop only for the current iteration. Working too far ahead risks doing work that will be thrown away as requirements and design change over time.
Improve Code Efficiency
Code efficiency doesn't refer to creating small, compact code by using arcane tricks and shortcuts. In fact, the opposite is true; efficient code uses coding standards and best practices.
- Use coding standards to write readable and understandable code. Use best practices and proven techniques that are well understood by other developers.
- Develop flexible, extensible code. Design and implement code with design patterns, refactoring, and emergent design.

The “big design up front”, or BDUF, approach to design can lead to overdesign and unused code. The opposite approach, sometimes referred to as “you ain't gonna need it” or YAGNI, creates only what is needed at the moment, but it can lead to brittle designs and inefficient code. A compromise that creates only what currently is necessary, but tempers that with some thought for the future, is a better approach. Scott Bain's book Emergent Design2 describes such an approach.
Lean Principles
- Eliminate Waste: Frequent, small integrations are more efficient than an extended integration phase.
- Build Quality In: Automated tests executed regularly and in a consistent manner prevent defects.
SHORT ITERATIONS
Iterations are complete development cycles resulting in the release of functional software. Traditional development methodologies often have iterations of six months to a year, but Lean Software Development uses much shorter iterations, typically 2 to 4 weeks. Short iterations generate customer feedback, and more feedback means more chances to adjust the course of development.
Feedback and Course Corrections
Feedback from the customer is the best way to discover what's valuable to them. Each delivery of new functionality creates a new opportunity for feedback, which in turn drives course corrections due to clarification of the customer's intent or actual changes to the requirements. Short iterations produce more feedback opportunities and allow more course corrections, so developers can hone in on what the customer wants.

Figure 5: Course Corrections
Using Short Iterations
Several techniques aid in the implementation of a process using short iterations:
- Work requirements in priority order. High priority requirements typically are well-defined, easiest to implement, and provide the most functionality in a short period of time.
- Define a non-negotiable end date for the iteration; sacrifice functionality to keep the team on schedule. End dates focus the team on delivering the required functionality. Even if some features are not completed, delivering those that are ensures customers get new functionality on a regular basis.
- Mark the end of the iteration with a demo and an official handoff to the customer. Demos foster pride in the product by allowing the team to show off its work.
- Deliver the product to the customer, whether it's a ready-for-deployment application or an interim release. Getting the product in the customer's hands for in-depth evaluation is the best way to generate feedback.

Teams struggling to complete iterations successfully are often tempted to lengthen their iterations; however, longer iterations tend to hide problems. Instead, struggling teams should reduce the iteration length, which reduces the scope, focuses the team on a smaller goal, and brings impediments to the surface more quickly so they can be resolved.
Lean Principles
- Eliminate Waste: Frequent, small integrations are more efficient than an extended integration phase.
- Deliver Fast: New, functional software is delivered to the customer in closely-spaced intervals.
CUSTOMER PARTICIPATION
Customer participation in traditional projects typically is limited to requirements specification at the beginning of the project and acceptance testing at the end. Collaboration between customers and developers in the intervening time is limited, typically consisting of status reports and the occasional design review.
Lean Software Development approaches customer participation as an on-going activity spanning the entire development effort. Customers write requirements and developers produce functional software from those requirements. Customers provide feedback on the software and developers act on that feedback, ensuring developers are producing what the customer really wants.
Involve the Customer
Key to establishing effective customer collaboration is involving the customer in the entire development process, not just at the beginning and end. Engaging the customer, reporting status, and providing a feedback path all help keep the customer involved.
- Engage the customer by having them write and prioritize the requirements. Customers get a sense of ownership, and they can direct the course of development.
- Have the customers write the acceptance tests (or at least specify their content), and, if possible, run the tests as well. Involvement in testing the product allows customers to specify exactly what it means to satisfy a requirement.
- Provide useful, easily-accessible status. For example, a list of the requirements in work and the status of each. Include status on problems affecting development to avoid surprises.
- Provide access to the product so the customer can see for themselves how it works, and provide a simple, direct feedback path so customers can input feedback easily.
Collaborate
Collaborating directly with the customer is necessary for developers to refine the requirements and understand exactly what the customer wants.
- Designate a customer representative. The representative writes and/or collects requirements and prioritizes them. The representative clarifies requirements for developers.
- Schedule face-to-face time with the customer. At the very least, include a demo at the end of each iteration.

Actual customers make the best customer representatives, but when customer representatives are not available a customer proxy can fill the role. A customer proxy should be from the development team's organization and must have a good understanding of the customer's needs and business environment.
Lean Principles
- Create Knowledge: Through collaboration, requirements are discovered and refined over time.
- Defer Commitment: Involving customers throughout the process eliminates the need to make decisions up front.
SUMMARY
Most discussions of Lean Software Development don't define specific practices for implementing the process, and the large number of Agile methodologies to choose from can leave newcomers confused and uncertain where to start. The specific practices outlined here provide a step-by-step approach to implementing a Lean Software Development process. Adopt one, several, or all the practices and take your first step into the world of Lean Software Development.
References
1 Implementing Lean Software Development: From Concept to Cash, Poppendieck/Poppendieck, Addison-Wesley Professional, 2006
2 Moving Toward Stillness, Lowry, Tuttle Publishing, 2000.
3 Emergent Design: The Evolutionary Nature of Professional Software Development, Bain, Addison-Wesley Professional, 2008
Some of the concepts and material in this Refcard were adapted from The Art of Lean Software Development, Hibbs/ Jewett/Sullivan, O'Reilly Media, 2009.
Eclipse Plug-in Development
By James Sugrue
17,379 Downloads · Refcard 70 of 187 (see them all)
Download
FREE PDF
The Essential Eclipse Plug-in Cheat Sheet
Eclipse Plug-in Development
About Eclipse Plug-ins
The Eclipse platform consists of many plug-ins, which are bundles of code that provide some functionality to the entire system. Plug-ins contribute functionality to the system by implementing pre-defined extension points. You can provide extension points in your own plug-in to allow other plug-ins to extend your functionality.

How plug-ins work
A plug-in describes itself to the system using an OSGi manifest (MANIFEST.MF) file and a plug-in manifest (plugin.xml) file. The Eclipse platform maintains a registry of installed plug-ins and the function they provide. As Equinox, the OSGi runtime, is at the core of Eclipse, you can think of a plug-in as an OSGi bundle. The main difference between plug-ins and bundles is that plug-ins use extension points for interaction between bundles.
Plug-ins take a lazy-loading approach, where they can be installed and available on the registry but will not be activated until the user requests some functionality residing in the plug-in.
the osgi manifest
MANIFEST.MF, usually located in the META-INF directory, deals with the runtime details for your plug-in. Editing of the manifest can be done through the editor provided, or directly in the MANIFEST.MF tab. The following is an example of one such manifest for a simple plug-in:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Myplugin
Bundle-SymbolicName: com.dzone.tests.myplugin
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.dzone.tests.myplugin.Activator
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
The Eclipse OSGi Framework implements the complete OSGi R4.1 Framework specification and all of the Core Framework services. Here we list the most common manifest headers and directives.
| Manifest Entry | Use | Example |
| Manifest-Version | Manifest versioning information for your own records | 1.0 |
| Bundle-ManifestVersion | A bundle manifest mayexpress the version of the syntax in which it is written by specifying a bundle manifest version. If using syntax from OSGi Release 4 or later, you must specify a bundle manifest version. The bundle manifest version defined by OSGi Release 4 is '2'. | 2 |
| Bundle-Name | Human readable name for the plug-in. | MyPlugin |
| Bundle-SymbolicName | A unique name for this plug-in, usually in package naming convention. | com.dzone.tests.myplugin |
| Bundle-Version | The version of this plugin. This should follow the typical three number versioning format of < major version>. <minor version>. < revision> This can also be appended by an alphanumeric qualifier. | 1.0.1.alpha |
| Bundle-Activator | The activator, or plug-in class, that controls this plug-in. | com.dzone.tests.myplugin.Activator |
| Bundle-Vendor | Human readable string for the plug-in provider. | DZone |
| Bundle-Classpath | A comma-separated list of directories and jar files used to extend this bundle's functionality. | lib/junit.jar,lib/xerces.jar |
| Require-Bundle | A comma-separated list of symbolic names of other bundles required by this plug-in. | rg.eclipse.ui,org.eclipse. core.runtime |
| Bundle-ActivationPolicy | Manifest header identifying the bundle's activation policy. This replaces the deprecated Eclipse-LazyStart directive. | Lazy |
| Bundle-Required ExecutionEnvironment | Manifest header identifying the required execution environment for the bundle. The platform may run this bundle if any of the execution environments named in this header match one of the execution environments it implements. | JavaSE-1.6 |
| Export-package | A list of the packages that this bundle provides for export to other plug-ins. | com.dzone.tests.api |
Plug-in Runtime
The Require-bundle manifest header has some extra functionality to help you manage your runtime dependencies. Bundles can be marked as optional dependencies by annotating the bundle with ;resolution:=optional.
You can also manage which version of the bundle your dependent on needs to be present using the ;bundleversion=' <values>' annotation. Here, the <values> that we refer to are a range of versions where you can specify minimum and maximum version ranges. The syntax of this range value is illustrated through these examples:
| Example | Meaning |
| 3.5 | Dependent only on version 3.5 of this bundle |
| [3.5, 3.5.1] | Must be either version 3.5 or 3.5.1 |
| [3.0, 4.0] | Must be a version of 3.0 or over, but not 4.0 |
Additional Eclipse Bundle Headers
Eclipse provides a number of addition bundle headers and directives. These extra headers are not part of the OSGi R4.1 specification, but allow developers to use additional Eclipse OSGi Framework functionality.
| Manifest Entry | Use | Example |
| Export-Package | Additional directives are available to manage the access restriction of exported packages. x-internal The default value for this property is false. When internal packages are specified as true using this option, the Eclipse PDE discourages their use. x-friends This option is similar to x-internal, but allows certain bundles to use the exported packages that have this option. Other bundles are discouraged. The x-internal option takes precedence over x-friends. |
Export-Package: org.eclipse. foo.internal; x-internal:=true Export-Package: org.eclipse.foo. formyfriends; x-friends:='org. eclipse.foo. friend1' |
| Eclipse-PlatformFilter | This allows you to set particular rules for your bundle before it can start. osgi.nl for language osgi.os for operating system osgi.arch for architecture osgi.ws for windowing system |
Eclipse- PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=x86)) |
All entries in the manifest can be internationalized by moving them to a separate plugin.properties file.
the plug-in manifest
With the Manifest.MF file looking after the runtime dependencies, plugin.xml deals with the plug-in extensions and extension points.
An extension allows you to extend the functionality of another plug-in in your system. An extension can be added through the plug-in editor's Extensions tab, or to your plugin.xml.
<extension point='org.eclipse.ui.preferencePages'>
<page
class='com.dzone.tests.myplugin.preferences.
SamplePreferencePage'
id='com.dzone.tests.myplugin.preferences.
SamplePreferencePage'
name='Sample Preferences'>
</page>
</extension>
Each extension point has a XML schema which specifies the elements and attributes that make up the extension. As you can see in the listing above, each extension point has a unique identifier. The <page> element above is specified in the XML schema for the org.eclipse.ui.preferencesPages extension.

You can also define your own extension points, and we will detail that process in a later section.
Plug-in mode l
The plug-in class is a representation of your plug-in running in the Eclipse platform. A plug-in class in Eclipse must extend org. eclipse.core.runtime.Plugin, which is an abstract class that provides generic facilities for managing plug-ins. When using the project wizard in the PDE, this class typically gets assigned Activator as its default name. Whatever name you assign to this plug-in class, it must be the same as that mentioned in the Bundle-Activator directive of your MANIFEST.MF.
The class has start and stop methods that refer to the BundleContext and are provided by the BundleActivator interface. These methods allow you to deal with the plug-ins lifecycle, so that you can do both initialization and cleanup activities at the appropriate times. When overriding these methods be sure to always call the superclass Implementations.

Bundle Context
A BundleContext is associated with your plug-in when it is started. As well as providing information about the plug-in, the BundleContext can provide information about other plug-ins in the system. By providing a listener to BundleEvent, you can monitor the lifecycle of any other plug-in.
Bundle
The terms Bundle and Plug-in may be used interchangeably when discussing Eclipse. The Bundle class provides us with the OSGi unit of modularity. There are six states associated with bundles:
| State | Meaning |
| UINSTALLED | The bundle is uninstalled and not available. |
| INSTALLED | A bundle is in the INSTALLED state when it has been installed in the Framework but is not or cannot be resolved |
| RESOLVED | Before a plug-in can be started, it must first be in the
RESOLVED state. A bundle is in the RESOLVED state when the Framework has successfully resolved the bundle's code dependencies. |
| STARTING | A bundle is in the STARTING state when its start method is
active. If the bundle has a lazy activation policy, the bundle may remain in this state until the activation is triggered. |
| STOPPING | A bundle is in the STOPPING state when its stop method
is active. When the BundleActivator.stop method completes the bundle is stopped and must move to the RESOLVED state. |
| ACTIVE | A bundle is in the ACTIVE state when it has been successfully started and activated. |
Lazy Loading
Plug-ins are normally set to load lazily, so that the code isn't loaded into memory until it is required. This is normally a good thing as you don't want to affect the startup time of Eclipse. If you do require your plug-in to start up and load when Eclipse launches, you can use the org.eclipse.ui.startup extension point.
<extension point='org.eclipse.ui.startup'>
<startup class='com.myplugin.StartupClass'>
</extension>
The startup class listed above must implement the org.eclipse.ui.IStartup interface which provides an earlyStartup() method. The method is called in a separate thread after the workbench initializes.
Extension Points
The Eclipse platform provides a number of extension points that you can hook into, to provide additional functionality. The concept behind an extension point is that a class provides some extendable behavior, and publishes this behavior as an extension point. In order to run this code, the plug-in requires a host '" in this case your own plug-in.
In your plugin.xml you take this extension point and provide extra information to help it run. You will usually need to provide some class that implements a particular interface in order to do this.
Here we will run through some useful extension points in the Eclipse platform. Note, that to make some of these available for your plug-in, you will usually need to add dependencies.
| Example | Meaning |
| org.eclipse.core.runtime .preferences | Allows plug-ins to use the Eclipse preferences mechanism, including the setting of default preference values. |
| org.eclipse.core.runtime .applications | A plug-in that wishes to use the platform but control all aspects of its execution is an application. |
| org.eclipse.core.resources .builders | Useful for IDE builders who wish to provide an incremental project builder, processing a set of resource changes. |
| org.eclipse.core.resources .markers | Markers are used to tag resources with use information '" this marker can then be utilized in the problems view. |
| org.eclipse.ui.activities | The activity extension point allows the filtering of plug-in contributions from users until they wish to use them. |
| org.eclipse.ui.editors | Allows the addition of new editors to the workbench, which can be tied to particular file extension types. |
| org.eclipse.ui.intro | When Eclipse is first started up the welcome page, or intro is displayed. This extension point allows contributions to the welcome page. |
| org.eclipse.ui.menus | Allows custom menus to be added to the workbench either in the main menu, toolbar or popup menus through the locationURI attribute. |
| org.eclipse.ui.perspective | Allows the addition of a perspective factory to the workbench, defining a particular layout of windows. |
| org.eclipse.ui.propertyPages | Adds a property page for objects of a given type. |
| org.eclipse.ui.themes | Allows the customization of the user interface, overriding the default colors and fonts. |
| org.eclipse.ui.views | Provides the ability to add views to the workbench. |
Creating your own extension points
As well as being a user of extension points, a plug-in can provide its own extensions for other plug-ins. Extension points allow loose coupling of functionality '" your plug-in exposes a set of interfaces and an extension point definition for others to use.
Extension Point Definition
You can create your extension point through the plugin.xml file, or through the Add button in the Extension Points tab of the plug-in editor.
For identifying your extension point you need to provide a unique identifier and a human readable name. At this point you can also point to a schema file and edit it afterwards. An extension point schema must have .exsd as its suffix.

Figure 1: The New Extension Point Wizard
Defining an Extension Point Schema
The PDE provides an editor for defining your .exsd file, consisting of three tabs. First, the Overview tab allows you to provide documentation and examples for your extension point. This is an essential step if you want your extension point to be adopted. Next, the Definition tab presents a graphical way to define your schema, while the Source tab allows editing of the .exsd XML definition.

Figure 2: The Extension Point editor
When creating your extension point, you will first want to create one or more elements with attributes that will be used. Each extension point attribute has a number of associated properties:
| Attribute | Use |
| Name | The name of the extension point attribute. |
| Deprecated | Whether the attribute is deprecated or not. |
| Use | Whether the attribute is optional, required or default. Default allows you to specify a value for the attribute if it hasn't been used. |
| Type | The available types are Boolean, String, Java, Resource and Identifier. While Boolean and String are self '"explanatory, Resource should be used if the attribute is a file. Identifier provides a reference id for the extension point. |
| Extends | If the type is Java this must be the name of the class that the attribute must extend. |
| Implements | If the type is Java this must be the name of the class that the attribute must implement. |
| Translatable | If the type is String this Boolean value indicates whether the attribute should be translated. |
| Restrictions | If the type is String this can be used to limit the choice of value to a list of strings. |
| Description | Attribute documentation. |
| References | If the type is Identifier, this provides the id of the extension point that you want to reference. This will allow implementers of the extension point to easily find the id, without having to look through the plug-in registry. |
Once you have created your elements and attributes for the extension point, the element can be added to a sequence for this extension. You can control the multiplicity of your extension here.
The mapping of XML to extension point declaration is simple; for users of your point, an xml element in the extension point will always appear on the left hand side tree, as part of the extension point declaration, while the xml attributes will appear as extension point attributes.
The Code Behind an Extension Point
With the extension point defined, the producer of this needs to provide some implementation that makes use of any extension point contributions.
To get a list of all the implementers of your extension point you can query the extension registry as follows, providing your extension point identifier as the parameter.
IConfigurationElement[] config = Platform.getExtensionRegistry()
.getConfigurationElementsFor('myextid');
To use the implementing extension point, you can get the object from the IConfigurationElement.
final Object o = config[i].createExecutableExtension('class');
Useful Tools
The PDE plug-in editor provides a number of useful utilities for working with your plug-ins. The Dependencies tab in particular is essential for organizing your runtime.

From here you can investigate the plug-in dependency hierarchy, starting with your plug-in as the root. You can also see which plug-ins are dependent on your own plug-in, as well as find any unused dependencies. This can be useful if you previously added a dependency to use an extension point, but have found that it is since no longer required. Finally, and most importantly, the tab provides a utility for investigating for cyclic dependencies.
Another useful tool for plug-in development is the Plug-in Registry view. This can be accessed from the Window>Show View>Other..>Plug-in Development category. This view will display all the plug-ins that are currently available in your Eclipse installation.

Figure 4: Plug-in Registry

Logging
It is recommended to log to a file, rather than using System. out. The Activator or plug-in class provides a facility to access the plug-in logging mechanism through the getLog() method, returning the org.eclipse.core.runtime.ILog interface.
Each log entry using this framework is of type IStatus. Any CoreExceptions thrown in Eclipse have an associated IStatus object. An implementation of this interface, Status, is available for use. There is also a MultiStatus class which allows multiple statuses to be logged at once.
Distributing your PL ug-in
Since Eclipse 3.4, p2 has been used as the method to provision your application with new or updated plug-ins. For build managers who have used the Update Site mechanism before, there doesn't need to be any change.
To create an update site you can use the wizard provided to create a new site.xml file. Using the Software Updates menu, users can point to your update site on the web and download the plug-in.
By adding some extra functionality over this simple implementation, you can leverage p2 to add extra meta data to your update site, which will make the installation experience faster for end users.
p2 Update Site Publisher
The UpdateSite Publisher application is provided by p2 to generate an artifact.xml and content.xml files for your standard update site. You can run this application in headless mode using org.eclipse.equinox.p2.publisher.UpdateSitePublisher. The following shows an example of how to run this application, taken from the p2 wiki.
java -jar <targetProductFolder>/plugins/org.eclipse.equinox.
launcher_*.jar
-application org.eclipse.equinox.p2.publisher.UpdateSitePublisher
-metadataRepository file:/<some location>/repository
-artifactRepository file:/<some location>/repository
-source /< location with a site.xml>
-configs gtk.linux.x86
-compress
-publishArtifacts
Read more about p2 at http://wiki.eclipse.org/Equinox/p2
Enha ncing your plug-in
When developing your plug-in, you should be aware of the wide variety of projects available in the Eclipse eco-system that help make your development easier and faster. This section gives an overview of just a few of the useful projects that exist, and explains how they can be used in your project.
Eclipse Modeling Project
http://eclipse.org/modeling/
The Eclipse Modelling Project provides a large set of tools for model driven development. The most popular part of this project is the Eclipse Modelling Framework (EMF). Using this technology, you can define a model in the ecore format, generate Java code to represent, serialise and de-serialise the model. Other tools within the modelling project utilise EMF to provide more specialised frameworks for developers.
The Connected Data Objects (CDO) project provides a threetier architecture for distributed and shared models.
The Graphical Modelling Framework (GMF) allows you to generate graphical editors for your model based on EMF and the Graphical Editing Framework (GEF). For developers who want to provide textual editor for their own language or DSL, XText provides a EBNF grammar language and generates a parser, meta-model and Eclipse text editor from this input.
Eclipse Communication Framework
http://eclipse.org/ecf
If your plugin requires any communication functionality, the ECF project is the first place to look. ECF consists of a number of bundles that expose various communication APIs. These APIs range from instant messaging, dynamic service discovery, file transfer to remote and distributed OSGi. Real-time shared editing functionality is also available in the framework, allowing you to collaborate remotely on anything that you are editing within your plug-in's environment.
Business Intelligence and Reporting Tools
http://eclipse.org/birt
BIRT is an open source reporting system based on Eclipse. BIRT provides both programmatic access to report creation, as well as functionality to create your own report template within the Eclipse IDE. While BIRT allows you to generate reports in file formats such as PDF, it is also possible to use BIRT on an application server to serve reports through a web browser.
Equinox
http://eclipse.org/equinox
As we have described in this card, Equinox is the Eclipse implementation of the OSGi R4 core framework specification, and provides the real runtime for all your plug-ins. However, as well as running your plug-ins on the desktop on an instance of Eclipse, you can take Equinox and run it on a server, allowing your plug-in to run on browsers as well as the desktop.
Rich Ajax Platform
http://eclipse.org/rap
With the emergence of the web as a real platform for rich applications, the Rich Ajax Platform allows you to take a standard RCP project, and with some minor modifications, make it deployable to the web. This idea of single-sourcing is key to the RAP project, and reduces the burden for developers to make an application ready for either the desktop or the web.
The same programming model is used, while qooxdoo is used for the client side presentation of your SWT and JFace widgets.
Getting Started with ASP.NET MVC 1.0
By Simone Chiaretta and Keyvan Nayyeri
15,654 Downloads · Refcard 69 of 187 (see them all)
Download
FREE PDF
The Essential ASP.NET MVC Cheat Sheet
Getting Started with ASP.NET MVC 1.0
Introduction
ASP.NET MVC is a new framework for building Web applications developed by Microsoft; it was found that the traditional WebForm abstraction, designed in 2000 to bring a “desktop-like” development experience to the Web, was sometimes getting in the way, and could not provide proper separation of concerns, so it was difficult to test. Therefore a new, alternative framework was built in order to address the changing requirements of developers. It was built with testability, extensibility and freedom in mind.
This Refcard will first explain how to setup your environment to work with ASP.NET MVC and how to create an ASP.NET MVC Web application. Then it will go deeper in details explaining the various components of the framework and showing the structure of the main API. Finally, it will show a sample of standard operation that developers can do with ASP.NET MVC.
Prerequisites
The ASP.NET MVC is a new framework, but it’s based on ASP.NET core API: in order to understand and use it, you have to know the basic concepts of ASP.NET. Furthermore, since it doesn’t abstract away the “Web” as the traditional WebForm paradigm does, you have to know HTML, CSS and JavaScript in order to take full advantage of the framework.
Installation
To develop a Web site with ASP.NET MVC, all you need is Visual Studio 2008 and the .NET Framework 3.5 SP1. If you are an hobbyist developer you can use Visual Web Developer 2008 Express Edition, which can be downloaded for free at the URL: http://www.microsoft.com/express/vwd/.
You also need to install the ASP.NET MVC library, which can be downloaded from the official ASP.NET Web site at http://www.asp.net/mvc/download.
You can also download everything you need, the IDE, the library, and also a free version of SQL Server (Express Edition) through the Web Platform Installer, available at: http://www.microsoft.com/web/.
The MVC pattern
As you probably have already guessed from the name, the framework implements the Model View Controller (MVC) pattern.

The UI layer of an application is made up of 3 components:
| MVC Component | Description |
| Model | The component responsible for data interactions with data storage system (typically a database) and main business logic implementations. |
| View | The component responsible for displaying data passed from Controller to it which also renders the user interface of the site. |
| Controller | The component that acts like a bridge between the model and the view to load data based on the request and pass them to view, or pass the data input by user to the model. |
And the flow of an operation is depicted in the diagram:
- The request hits the Controller.
- The Controller delegates the execution of “main” operation to the Model.
- The Model sends the results back to the Controller.
- The Controller formats the data and sends them to the View.
- The View takes the data, renders the HTML page, and sends it to the browser that requested it.
Build your first application
Starting the developing of an ASP.NET MVC application is easy. From Visual Studio just use the “File > New Project” menu
command, and select the ASP.NET MVC Project template (as shown in the following figure).

Type in the name of the project and press the “OK” button. It will ask you whether you want to create a test project (I suggest choosing Yes), then it will automatically create a stub ASP.NET MVC Web site with the correct folder structure that you can later customize for your needs.

As you can see, the components of the applications are wellseparated in different folders.
| Folder Name | Contains |
| /Content | Static contents for your site, like CSS and images |
| /Controllers | All the Controllers of the application, one per file |
| /Models | The classes that encapsulate the interaction with the Model |
| /Scripts | The JavaScript files used by your application (by default it contains jQuery |
| /Views | All the views of the application, in sub-folders that are related one to one with the controllers |
The Fundame ntals of ASP.NET MVC
One of the main design principles of ASP.NET MVC is “convention over configuration”, which allows components to fit nicely together based on their naming conventions and location inside the project structure.
The following diagram shows how all the pieces of an ASP.NET MVC application fit together based on their naming conventions:

Routing
The routing engine is not part of the ASP.NET MVC framework, but is a general component introduced with .NET 3.5 SP1. It is the component that is first hit by a request coming from the browser. Its purpose is to route all incoming requests to the correct handler and to extrapolate from the URL a set of data that will be used by the handler (which, in the case of an ASP.NET MVC Web application, is always the MvcHandler) to respond to the request.

To accomplish its task, the routing engine must be configured with rules that tell it how to parse the URL and how to get data out of it. This configuration is specified inside the RegisterRoutes method of the Global.asax file, which is in the root of the ASP.NET MVC Web application.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
“Default”, //Route Name
“{controller}/{action}/{id}”, //Route Formats
new { controller = “Home”, action = “Index”, id = “” } //Defaults
);
}
The snippet above shows the default mapping rule for each ASP.NET MVC application: every URL is mapped to this route, and the first 3 parts are used to create the data dictionary sent to the handler. The last parameter contains the default values that must be used if some of the URL tokens cannot be populated. This is required because, based on the default convention, the data dictionary sent to the MvcHandler must always contain the controller and the action keys.
Examples of other possible route rules:
| URL | Rule | Data Dictionary |
| /Posts/Show/5 |
|
Controller = Posts Action = Show Id = 5 |
| /archive/2009-10-02/MyPost |
|
|
Model
ASP.NET MVC, unlike other MVC-based frameworks like Ruby on Rails (RoR), doesn’t enforce a convention for the Model. So in this framework the Model is just the name of the folder where you are supposed to place all the classes and objects used to interact with the Business Logic and the Data Access Layer. It can be whatever you prefer it to be: proxies for Web services, ADO.NET Entity Framework, NHibernate, or anything that returns the data you have to render through the views.
Controller
The controller is the first component of the MVC pattern that comes into action. A controller is simply a class that inherits from the Controller base class whose name is the name of a controller and ends with “Controller,” and is located in the Controllers folder of the application folder structure. Using that naming convention, the framework automatically calls the specified controller based on the parameter extrapolated by the URL.
namespace MyMvcApp.Controllers
{
public class PageController : Controller
{
//Controller contents.
}
}
The real work, however, is not done by the class itself, but by the method that lives inside it. These are called Action Methods.
Action Method
An action method is nothing but a public method inside a Controller class. It usually returns a result of type ActionResult and accepts an arbitrary number of parameters that contain the data retrieved from the HTTP request. Here is what an action method looks like:
public ActionResult Show(int id)
{
//Do stuff
ViewData[“myKey”]=myValue;
return View();
}
The ViewData is a hash-table that is used to store the variables that need to be rendered by the view: this object is automatically passed to the view through the ActionResult object that is returned by the action. Alternatively, you can create your own view model, and supply it to the view.
public ActionResult Show(int id)
{
//Do stuff
return View(myValue);
}
This second approach is better because it allows you to work with strongly-typed classes instead of hash-tables indexed with string values. This brings compile-time error checking and Intellisense.
Once you have populated the ViewData or your own custom view model with the data needed, you have to instruct the framework on how to send the response back to the client. This is done with the return value of the action, which is an object that is a subclass of ActionResult. There are various types of ActionResult, each with its specific way to return it from the action.
| ActionResult Type | Method | Purpose |
| ViewResult | View() | Renders a view whose path is inferred by the current controller and action: /View/controllerName/ ActionName.aspx |
| ViewResult | View(viewName) |
|
| ViewResult | View(model) | Renders the view using the default path, also passing a custom View Model that contains the data that needs to be rendered by the view. |
| PartialViewResult | PartialView() | Same as View, but doesn’t return a complete HTML page, only a portion of it. Looks for the file at following the path: /View/controllerName/ ActionName.ascx |
| PartialViewResult | PartialView(viewName) | Renders a partial view whose name is specified by the parameter: /View/controllerName/ viewName.ascx |
| PartialViewResult | PartialView(model) | Renders a partial view using the default path, also passing a custom View Model that contains the data that needs to be rendered by the partial view. |
| RedirectResult | Redirect(url) | Redirects the client to the URL specified. |
| RedirectToRouteResult | RedirectToAction(actionName) | Redirects the client to the action specified. Optionally you can specify also the controller name and an additional list of parameters. |
| RedirectToRouteResult | RedirectToR | Redirects the client to the route specified. Optionally you can specify an additional list of parameters. |
| ContentResult | Content(content) | Sends to the content specified directly to the client. Optionally you can specify the content type and encoding. |
| JsonResult | Json(data) | Serializes the data supplied in Json format and sends the Json string to the client. |
| FileResult | File(filename,contenttype) | Sends the specified file directly to the client. Optionally you can provide a stream or a byte array instead of a physical path. |
| JavaScriptResult | JavaScript(javascript) | Sends the script provided as external JavaScript file. |
| EmptyResult | new EmptyResult() | Doesn’t do anything: use this in case you handle the result directly inside the action (not recommended). |
Model Binder
Using the ActionResults and the ViewData object (or your custom view model), you can pass data from the Action to the view. But how can you pass data from the view (or from the URL) to the Action? This is done through the ModelBinder. It is a component that retrieves values from the request (URL parameters, query string parameters, and form fields) and converts them to action method parameters.
As everything in ASP.NET MVC, it’s driven by conventions: if the action takes an input parameter named Title, the default Model Binder will look for a variable named Title in the URL parameters, in the query string, and among the values supplied as form fields.

But the Model Binder works not only with simple values (string and numbers), but also with composite types, like your own objects (for example the ubiquitous User object). In this scenario, when the Model Binder sees that an object is composed by other sub-objects, it looks for variables whose name matches the name of the properties of the custom type. Here it’s worth taking a look at a diagram to make things clear:

View
The next and last component is the view. When using the default ViewEngine (which is the WebFormViewEngine) a view is just an aspx file without code-behind and with a different base class.
Views that are going to render data passed only through the ViewData dictionary have to start with the following Page directive:
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master”
Inherits=”System.Web.Mvc.ViewPage” %>
If the view is also going to render the data that has been passed via the custom view model, the Page directive is a bit different, and it also specifies the type of the view model:
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master”
Inherits=”System.Web.Mvc.ViewPage<PageViewModel>” %>
You might have noticed that, as with all normal aspx files, you can include a view inside a master page. But unlike traditional Web forms, you cannot use user controls to write your HTML markup: you have to write everything manually. However, this is not entirely true: the framework comes with a set of helper methods to assist with the process of writing HTML markup. You’ll see more in the next section.

HTML helper
You probably don’t want to go back writing the HTML manually, and neither does Microsoft want you to do it. Not only to help you write HTML markup, but also to help you easily bind the data passed from the controller to the view, the ASP.NET MVC Framework comes with a set of helper methods collectively called HtmlHelpers. They are all methods attached to the Html property of the ViewPage. For example, if you want to write the HTML markup for a textbox you just need to write:
<%= Html.Textbox(“propertyName”)%>
And this renders an HTML input text tag, and uses the value of the specified property as the value of the textbox. When looking for the value to write in the textbox, the helper takes into account both the possibilities for sending data to a view: it first looks inside the ViewData hash-table for a key with the name specified, and then looks inside the custom view model, for a property with the given name. This way you don’t have to bother assigning values to input fields, and this can be a big productivity boost, especially if you have big views with many fields.
Let’s see the HtmlHelpers that you can use in your views:
| Helper | Purpose |
|
Renders a HTML link with the text specified, pointing to the URL that represents the action and the other optional parameters specified (controller and parameters). If no optional parameters are specified, the link will point to the specified action in the current controller. |
|
Renders a HTML link as the method ActionLink, but now using the route values, and optionally the route name, as input. |
| Html.BeginForm(actionName,…) | Renders the beginning HTML form tag, setting as action of the form the URL of the action specified. The URL creation works exactly the same as the ActionLink method. |
| Html.EndForm() | Renders the form closing tag. |
| Html.Textbox(name) | Renders a form input text box, populating it with the value retrieved from the ViewData or custom view model object. Optionally you can specify a different value for the field, or specify additional HTML attributes. |
| Html.TextArea(name, rows, cols, …) | Same as Textbox, but renders a textarea, of the specified row and column size. |
| Html.Checkbox(name) | Renders a checkbox. |
| Html.RadioButton(name, value) | Renders a radio button with the given name, the given value and optionally specifying the checked state. |
| Html.Hidden(name) | Renders a form input field of type hidden. |
|
Renders a select HTML element, reading the options from the selectList variable, which is a list of name-value pairs. |
|
Same as the DropDownList method, but enables the ability to select multiple options. |
|
Displays a validation message if the specified field contains an error (handled via the ModelState). |
| Html.ValidationSummary(…) | Displays the summary with all the validation messages of the view. |
|
Renders on the view the contents of the specified partial view. |
As alternative to writing Html.BeginForm and Html.CloseForm methods, you can write an HTML form by including all its elements inside a using block:
<% using(Html.BeginForm(“Save”)) { %>
<!—all form elements here -->
<% } %>
To give you a better idea of how a view that includes an editing form looks like, here is a sample of a complete view for editing an address book element:
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master”
Inherits=”System.Web.Mvc.ViewPage<EditContactViewModel>” %>
<% using(Html.BeginForm(“Save”)) { %>
Name: <%= Html.Textbox(“Name”) %> <br/>
Surname: <%= Html.Textbox(“Surname”) %> <br/>
Email: <%= Html.Textbox(“Email”) %> <br/>
Note: <%= Html.TextArea(“Notes”, 80, 7, null) %> <br/>
Private <%= Html.Checkbox(“IsPrivate”) %><<br/>
<input type=”submit” value=”Save”>
<% } %>
T4 Templates
But there is more: bundled with Visual Studio there is a template engine (made T4 as in Text Template Transformation Toolkit) that helps automatically generate the HTML of your views based on the ViewModel that you want to pass to the view.
The “Add View” dialog allows you to choose with which template and based on which class you want the views to be generated
| Template Name | Purpose |
| Create | Generates a form to create a new instance of the item you selected |
| Details | Generates a view that shows all the properties of the item you selected |
| Edit | Generates a form to edit a instance of the item you selected |
| Empty | Generates an empty view, only with the declaration of the class it’s based on |
| List | Generates a view with a list of the items you selected |

What these templates do is mainly iterating over all the properties of the ViewModel class and generating the same code you would have probably written yourself, using the HtmlHelper methods for the input fields and the validation messages.
For example, if you have a view model class with two properties, Title and Description, and you choose the Edit template, the resulting view will be:
<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.
Master”
Inherits=”System.Web.Mvc.ViewPage<IssueTracking.Models.Issue>” %>
<asp:Content ID=”Content1” ContentPlaceHolderID=”TitleContent”
runat=”server”>
Edit
</asp:Content>
<asp:Content ID=”Content2” ContentPlaceHolderID=”MainContent”
runat=”server”>
<h2>Edit</h2>
<%= Html.ValidationSummary(“Edit was unsuccessful. Please correct
the errors and try again.”) %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields<</legend>
<p>
<label for=”Title”>Title:</label>
<%= Html.TextBox(“Title”, Model.Title) %>
<%= Html.ValidationMessage(“Title”, “*”) %>
</p>
<p>
<label for=”Description”>Description:</label>
<%= Html.TextArea(“Description”,
Model.Description,7,50,null)%>
<%= Html.ValidationMessage(“Description”, “*”) %>
</p>
<p>
<input type=”submit” value=”Save” />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink(“Back to List”, “Index”) %>
</div>
</asp:Content>
Ajax
The last part of ASP.NET MVC that is important to understand is AJAX. But it’s also one of the easiest aspects of the framework.
First, you have to include the script references at the top of the page where you want to enable AJAX (or in a master page if you want to enable itfor the whole site):
<script src=”/Scripts/MicrosoftAjax.js” type=”text/javascript”><script>
<script src=”/Scripts/MicrosoftMvcAjax.js” type=”text/javascript”></script>
And then you can use the only 2 methods available in the AjaxHelper: ActionLink and BeginForm.
They do the exact same thing as their HtmlHelper counterpart, just asynchronously and without reloading the page. To make the AJAX features possible, a new parameter is added to configure how the request and the result should be handled. It’s called AjaxOptions and is a class with the following properties:
| Parameter Name | Purpose |
| UpdateTargetId | The id of the html element that will be updated |
| InsertionMode | Where the new content will be inserted:
|
| Confirm | The question that will be asked to the user to confirm their will to proceed |
| OnBegin | Generates an empty view, only with the declaration of the class it’s based on |
| OnSuccess | Generates a view with a list of the items you selected |
| OnFailure | Name of the JavaScript function to be called before the request starts |
| OnComplete | Name of the JavaScript function to be called when the request is complete, either with a success or a failure |
| Url | The URL to sent the request to, if you want to override the URL calculated via the usual actionName and controllerName parameters |
| LoadingElementId | The id of the HTML element that will be made visible during the execution of the request |
For example, here is a short snippet of code that shows how to update a list of items using the AJAX flavor of the BeginForm method:
<ul id=”types”>
<% foreach (var item in Model) { %>
<li><%= item.Name %></li>
<% } %>
</ul>
<% using(Ajax.BeginForm(“Add”,”IssueTypes”,new AjaxOptions() {
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = “types”,
OnSuccess = “myJsFunc”
})) { %>
Type Name: <%= Html.TextBox(“Name”) %>
<input type=”submit” value=”Add type” />
<% } %>
The AJAX call will be sent to the Add action inside the IssueType controller. Once the request is successful, the result sent by the controller will be added after all the list items that are inside the types element. And then the myJsFunc will be executed.
But what the ASP.MVC library does is just enabling these two methods: if you want more complex interactions you have to use either the AJAX in ASP.NET library or you can use jQuery, which ships as part of the ASP.NET MVC library.
If you want to use the AJAX in ASP.NET library, you don’t have to do anything because you already referenced it in order to use the BeginForm method, but if you want to use jQuery, you have to reference it as well.
<script src=”/Scripts/jquery-1.3.2.js” type=”text/javascript”></script>
One benefit of having the jQuery library as part of the ASP.NET MVC project template is that you gain full Intellisense support. But there is an extra step to enable it: you have to reference the jQuery script both with the absolute URL (as above) needed by the application and with a relative URL, which is needed by the Intellisense resolution engine. So, at the end, if you want to use jQuery and enable Intellisense on it, you have to add the following snippet:
<script src=”/Scripts/jquery-1.3.2.js” type=”text/javascript”>
</script>
<% if(false> { %>
<script src=”../../Scripts/jquery-1.3.2.js” type=”text javascript”>
</script>
<% } %>
Getting Started with Oracle Berkeley DB
By Masoud Kalali
10,608 Downloads · Refcard 68 of 187 (see them all)
Download
FREE PDF
The Essential Berkeley DB Cheat Sheet
Getting Started with Oracle Berkeley DB
About Oracle Berkeley DB
The Oracle Berkeley DB (BDB) family consists of three open source data persistence products which provide developers with fast, reliable, high performance, enterprise ready local databases implemented in the ANSI C and Java programming languages. The BDB family typically stores key-value pairs but is also flexible enough to store complex data models. BDB and BDB Java Edition share the same base API, making it possible to easily switch between the two.
We will review the most important aspects of Oracle BDB family briefly. Then we will dig deep into Oracle BDB Java Edition and see what its exclusive features are. We discuss Based API and Data Persistence Layer API. We will see how we can manage transactions DPL and Base API in addition to persisting complex objects graph using DPL will form the overall development subjects. Backup recovery, tuning, and data migration utilities to migrate data between different editions and installations forms the administrations issues which we will discuss in this Refcard.
The BDB Family
Oracle BDB Core Edition
Berkeley DB is written in ANSI C and can be used as a library to access the persisted information from within the parent application address space. Oracle BDB provides multiple interfaces for different programming languages including ANSI C, the Java API through JNI in addition to Perl, PHP, and Python.
Oracle BDB XML Edition
Built on top of the BDB, the BDB XML edition allows us to easily store and retrieve indexed XML documents and to use XQuery to access stored XML documents. It also supports accessing data through the same channels that BDB supports.
BDB Java Edition
BDB Java Edition is a pure Java, high performance, and flexible embeddable database for storing data in a key-value format. It supports transactions, direct persistence of Java objects using EJB 3.0-style annotations, and provides a low level key-value retrieval API as well as an “access as collection” API.
Key Features
Each of the BDB family members supports different feature sets. BDB XML edition enjoys a similar set of base features as the Core BDB. BDB Java edition on the other hand is implemented in a completely different environment with an entirely different set of features and characteristics (See Table 4). The base feature sets are shown in Table 1.
| Table 1: Family Feature Sets | |
| Feature Set | Description |
| Data Store (DS) | Single writer, multiple reader |
| Concurrent Data Store (CDS) | Multiple writers, multiple snapshot readers |
| Transactional Data Store (TDS) | Full ACID support on top of CDS |
| High Availability (HA) | Replication for fault tolerance. Fail over recovery support |
Table 2 shows how these features are distributed between the different BDB family members.
| Table 2: Different Editions’ Feature Sets | DS | CDS | TS | HA |
| BDB/BDB XML Edition |
|
|
|
|
| BDB Java Edition |
|
|
Additional Features
The BDB family of products has several special features and offers a range of unique benefits which are listed in Table 3.
| Table 3: Family Features and Benefits | |
| Feature | Benefit |
| Locking | High concurrency |
| Data stored in application-native format | Performance, no translation required |
| Programmatic API, no SQL | Performance, flexibility/control |
| In process, not client-server | Performance, no IPC required |
| Zero administration | Low cost of ownership |
| ACID transactions and recovery | Reliability, data integrity |
| Dual License | Open/Closed source distributions |
| In memory or on disk operation | Transacted caching/ persisted data store |
| Similar data access API | Easy switch between JE and BDB |
| Just a set of library | Easy to deploy and use |
| Very large databases | Virtually no limit on database size |
Features unique to BDB Java Edition are listed in Table 4.
| Table 4: BDB Java Edition Exclusive Features | |
| Feature | Benefit |
| Fast, indexed, BTree | Ultra fast data retrieval |
| Java EE JTA and JCA support | Integration with Java EE application servers |
| Efficient Direct Persistence Layer | EJB 3.0 like annotation to store Java Objects graph |
| Easy Java Collections API | Transactional manipulation of Base API through enhanced Java Collections |
| Low Level Base API | Work with dynamic data schema |
| JMX Support | Monitor able from within parent application |
These features, along with a common set of features, make the Java edition a potential candidate for use cases that require caching, application data repositories, POJO persistence, queuing/buffering, Web services, SOA, and Integration.
Introducin g Berkeley DB java Edition
Installation
You can download BDB JE from http//bit.ly/APfJ5. After extracting the archive you’ll see several directories with selfdescribing names. The only file which is required to be in the class path to compile and run the included code snippet is je- 3.3.75.jar (the exact file name may vary) which is placed inside the lib directory. Notice that BDB JE requires J2SE JDK version 1.5.0_10 or later.

Access APIs
BDB JE provides three APIs for accessing persisted data. The Base API provides a simple key-value model for storing and retrieving data. The Direct Persistence Layer (DPL) API lets you persist any Java class with a default constructor into the database and retrieve it using a rich set of data retrieval APIs. And finally the Collections API which extends the well known Java Collections API with data persistence and transaction support over data access.
Base API sample
The Base API is the simplest way to access data. It stores a key and a value which can be any serializable Java object.
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
Environment dbEnv = new Environment(new File(“/home/masoud/dben”),
envConfig);
DatabaseConfig dbconf = new DatabaseConfig();
dbconf.setAllowCreate(true);
dbconf.setSortedDuplicates(false);//allow update
Database db = dbEnv.openDatabase(null, “SampleDB “, dbconf);
DatabaseEntry searchEntry = new DatabaseEntry();
DatabaseEntry dataValue = new DatabaseEntry(“ data content”.
getBytes(“UTF-8”));
DatabaseEntry keyValue = new DatabaseEntry(“key content”.
getBytes(“UTF-8”));
db.put(null, keyValue, dataValue);//inserting an entry
db.get(null, keyValue, searchEntry, LockMode.DEFAULT);//retrieving
record
String foundData = new String(searchEntry.getData(), “UTF-8”);
dataValue = new DatabaseEntry(“updated data content”.
getBytes(“UTF-8”));
db.put(null, keyValue, dataValue);//updating an entry
db.delete(null, keyValue);//delete operation
db.close();
dbEnv.close();
There are multiple overrides for the Database.put method to prevent duplicate records from being inserted and to prevent record overwrites.
DPL Sample
DPL sample consists of two parts, the entity class and the entity management class which handle CRUD over the entity class.
Entity Class
@Entity
public class Employee {
@PrimaryKey
public String empID;
public String lastname;
@SecondaryKey(relate = Relationship.MANY_TO_MANY,
relatedEntity = Project.class,onRelatedEntityDelete =
DeleteAction.NULLIFY)
public Set<Long> projects;
public Employee() { }
public Employee(String empID, String lastname, Set<Long> projects)
{
this.empID = empID;
this.lastname = lastname;
this.projects = projects;
}
}}
This is a simple POJO with few annotations to mark it as an entity with a String primary key. For now ignore the @Secondarykey annotation, we will discuss it later.
The data management Class
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
Environment dbEnv = new Environment(new File(“/home/masoud/dbendpl”),
envConfig);
StoreConfig stConf = new StoreConfig();
stConf.setAllowCreate(true);
EntityStore store = new EntityStore(dbEnv, “DPLSample”, stConf);
PrimaryIndex userIndex;
userIndex = store.getPrimaryIndex(String.class, Employee.class);
userIndex.putNoReturn(new Employee(“u180”, “Doe”, null));//insert
Employee user = userIndex.get(“u180”);//retrieve
userIndex.putNoReturn(new Employee(“u180”, “Locke”, null));//
Update
userIndex.delete(“u180”);//delete
store.close();
dbEnv.close();
These two code snippets show the simplest from of performing CRUD operation without using transaction or complex object relationships.
Sample code description
An Environment provides a unit of encapsulation for one or more databases. Environments correspond to a directory on disk. The Environment is also used to manage and configure resources such as transactions. EnvironmentConfig is used to configure the Environment, with options such as transaction configuration, locking, caching, getting different types of statistics including database, locks and transaction statistics, etc.
One level closer to our application is DatabaseConfig and Database object when we use Base API. When we use DPL these objects are replaced by StoreConfig and EntityStore.
In Base API DatabaseConfig and Database objects provide access to the database and how the database can be accessed.
Configurations like read-only access, record duplication handling, creating in-memory databases, transaction support, etc. are provided through DatabaseConfig.
In DPL StoreConfig and EntityStore objects provide access to object storage and how the object storage can be accessed. Configurations such as read only access, data model mutation, creating in-memory databases, transaction support, etc. are provided through StoreConfig.
The PrimaryIndex class provides the primary storage and access methods for the instances of a particular entity class. There are multiple overrides for the PrimaryIndex.put method to prevent duplicate entity insertion and provide entity overwrite prevention.

BDB Java edition environment anatomy
A BDB JE database consists of one or more log files which are placed inside the environment directory.
The log files are named NNNNNNNN.jdb where NNNNNNNN is an 8-digit hexadecimal number that increases by 1 (starting from 00000000) for each log file written to disk. BDB JE rolls to next file when the current file size reaches the predefined configurable size. The predefined size is 10MB.
A BDB database can be considered like a relational table in an RDBMS. In Base API we directly use the database we need to access, while in DPL we use an EntityStore which may interact with multiple databases under the hood.
Each BDB environment can contain tens of databases and all of these databases will be stored in a single row of log files. (No separate log files per-database). Figure 1 shows the concept visually.


Figure 1: BDB JE environment and log files.

BDB Java edition environment anatomy
Table 5 shows Base API characteristics and benefits. The keyvalue access model provides the most flexibility.
| Table 5: Base API Features |
| Key value store retrieval, value can be anything |
| Cursor API to traverse in a dataset forward and backward |
| JCA (Java Connectivity Architecture) support |
| JMX (Java Management eXtension) support |
| Table 6: DPL API Features |
| Type Safe access to persisted objects |
| Updating classes with adding new fields is supported |
| Persistent class fields can be private, package-private, protected or public |
| Automatic and extendable data binding between Objects and underlying storage |
| Index fields can be accessed using a standard java.util collection. |
| Java annotations are used to define metadata like relations between objects |
| Field refactoring is supported without changing the stored date.(Called mutation) |
Table 6 and Table 7 list the features that mostly determine when we should use which API. Table 7 lists possible use cases for each API.
| Table 7: Which API is suitable for your case | |
| Use case characteristics | Suitable API |
| Data model is highly dynamic and changing | Base API |
| Data model has complex object model and relationships | DPL |
| Need application portability between Java Edition and Core Edition | DPL, Base API |
Transaction Support
Transaction Support is an inseparable part of enterprise software development. BDB JE supports transaction and provides concurrency and record level locking. To add transaction support to DPL in our DPL sample code we can introduce the following changes:
...
envConfig.setTransactional(true);
stConf.setTransactional(true);
TransactionConfig txConf = new TransactionConfig();
stConf.setTransactional(true);
txConf.setReadCommitted(true);
Transaction tx= dbEnv.getThreadTransaction();
dbEnv.beginTransaction(tx, txConf);
...
userIndex.putNoReturn(tx, new Employee(“u180”, “Doe”, null));//
insert
...
tx.commit();
...
The simplicity of BDB JE Transaction Support makes it very suitable for transactional cache systems. The isolation level, deferrable and manual synchronization of transactional data with hard disk (Durability), replication policy, and transaction lock request and transaction lifetime timeout can be configured using the Transaction and TransactionConfig objects.

Transaction support in Base API is a bit different, as in Base API we directly deal with databases while in DPL we deal with environment and EntityStore objects. The following changes will allow transaction support in Base API.
...
envConfig.setTransactional(true);
dbconf.setTransactional(true);
TransactionConfig txConf = new TransactionConfig();
txConf.setSerializableIsolation(true);
txConf.setNoSync(true);
Transaction tx = dbEnv.getThreadTransaction();
tx.setLockTimeout(1000);
tx.setTxnTimeout(5000);
Database db = dbEnv.openDatabase(tx, «SmpleDB», dbconf);
dbEnv.beginTransaction(tx, txConf);
...
db.put(tx, keyValue, dataValue);//inserting an entry
...
tx.commit();
More transaction related supported features are demonstrated in this snippet. Environment, Database, EntityStore, etc. configuration is omitted from these snippet for sake of simplicity.

Persisting Complex Object Graph using DPL
For this section we leave Base API alone and focus on using DPL for complex object graphs. We continue with introducing secondary index and many-to-many mapping.
Let’s look at some important annotations that we have for defining the object model.
| Table 8: BDB JE annotations | |
| Annotation | Description |
| @Entity | Declares an entity class; that is, a class with a primary index and optionally one or more indices. |
| @PrimaryKey | Defines the class primary key and must be used one and only one time for every entity class. |
| @SecondaryKey | Declares a specific data member in an entity class to be a secondary key for that object. This annotation is optional, and can be used multiple times for an entity class. |
| @Persistent | Declares a persistent class which lives in relation to an entity class. |
| @NotTransient | Defines a field as being persistent even when it is declared with the transient keyword. |
| @NotPersistent | Defines a field as being non-persistent even when it is not declared with the transient keyword. |
| @KeyField | Indicates the sorting position of a key field in a composite key class when the Comparable interface is not implemented. The KeyField integer element specifies the sort order of this field within the set of fields in the composite key. |
We used two of these annotations in practice and you saw @SecondaryKey in the Employee class. Now we are going to see how the @SecondaryKey annotation can be used. Let’s create the Project entity which the Employee class has a many-to-many relation with.
@Entity
public class Project {
public String projName;
@PrimaryKey(sequence = «ID»)
public long projID;
public Project() {
}
public Project(String projName) {
this.projName = projName;
}
}
The @PrimaryKey annotation has a string element to define the name of a sequence from which we can assign primary key values automatically. The primary key field type must be numerical and a named sequence can be used for multiple entities.
Now let’s see how we can store and retrieve an employee with its related project objects.
...
PrimaryIndex<String, Employee> empByID;
PrimaryIndex<Long, Project> projByID;
empByID = store.getPrimaryIndex(String.class, Employee.class);
projByID = store.getPrimaryIndex(Long.class, Project.class);
SecondaryIndex<Long, String, Employee> empsByProject;
empsByProject = store.getSecondaryIndex(empByID, Long.class,
“projects”);
Set<Long> projects = new HashSet<Long>();
Project proj = null;
proj = new Project(“Develop FX”);
projByID.putNoReturn(proj);
projects.add(proj.projID);
proj = new Project(“Develop WS”);
projByID.putNoReturn(proj);
projects.add(proj.projID);
empByID.putNoReturn(new Employee(“u146”, “Shephard”, projects));//
insert
empByID.putNoReturn(new Employee(“u144”, “Locke”, projects));//
insert
EntityIndex projs = empsByProject.subIndex(proj.
projID);
EntityCursor<Employee> pcur = projs.entities();
for (Employee entity : pcur) {
//process the employees
}
EntityCursor<Employee> emplRange = empByID.entities(“e146”, true,
“u148”, true);
for (Employee entity : emplRange) {
//process the employees
}
emplRange.close();
pcur.close();
store.close();
dbEnv.close();
The Environment and EntityStore definitions are omitted. The SecondaryIndex provides primary methods for retrieving objects related to the Secondary Key of a particular object. The SecondaryIndex can be used to retrieve the related objects through a traversable cursor. We can also use SecondaryIndex to query for a specific range of objects in a given range for its primary key.
| Table 9: Supported Object Relation | |
| Relation | Description |
| ONE_TO_ONE | A single entity is related to a single secondary key value. |
| ONE_TO_MANY | A single entity is related to one or more secondary key values. |
| MANY_TO_ONE | One or more entities are related to a single secondary key value. |
| MANY_TO_MANYOne or more entities are related to one or more secondary key values. | |
A SecondaryIndex can be used to traverse over the collection of secondary key’s values to retrieve the secondary objects.

BDB JE Collections API
The only different between using BDB JE collections API and classic collections is the fact that when we use BDB JE Collections API we are accessing persisted objects instead of in-memory objects which we usually access in classic collection APIs.
| The Collections API Characteristics |
| An implementation Map, SortedMap, Set, SortedSet, and Iterator. |
| To stay compatible with Java Collections, Transaction is supported using TransactionWorker and TransactionRunner which the former one is the interface which we can implement to execute our code in a transaction and later one process the transaction. |
| Keys and values are represented as Java objects. Custom binding can be defined to bind the stored bytes to any type or format like XML, for example. |
| Data binding should be defined to instruct the Collections API about how keys and values are represented as stored data and how stored data is converted to and from Java objects. We can use one of the two (SerialBinding, TupleBinding) default data bindings or a custom data binding. |
| Environment, EnvironmentConfig, Database and DatabaseConfig stay the same as it was for Base API. |
| Collections API extends Java serialization to store class description separately to make data records much more compact. |
To get a real sense about BDB JE Collections API think of it as we can persist and retrieve objects using a collection class like SortedMap’s methods like tailMap, subMap or put, putall, get, and so on.
But before we use the SortedMap object to access the stored data, we need to initialize the base objects like Database and Environment; we should create the ClassCatalog object, and finally we should define bindings for our key and value types.
Collections API sample
Now let’s see how we can store and retrieve our our objects using Collections API. In this sample we are persisting a pair of Integer key and String value using SortedMap.
First lets analyze the TransactionWorker implementation.
public class TransWorker implements TransactionWorker {
private ClassCatalog catalog;
private Database db;
private SortedMap map;
public TransWorker(Environment env) throws Exception {
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setTransactional(true);
dbConfig.setAllowCreate(true);
Database catalogDb = env.openDatabase(null, “catalog”, dbConfig);
catalog = new StoredClassCatalog(catalogDb);
// use Integer tuple binding for key entries
TupleBinding keyBinding =
TupleBinding.getPrimitiveBinding(Integer.class);
// use String serial binding for data entries
SerialBinding dataBinding = new SerialBinding(catalog,
String.class);
db = env.openDatabase(null, “dben-col”, dbConfig);
map = new StoredSortedMap(db, keyBinding, dataBinding,
true);
}
/** Performs work within a transaction. */
public void doWork() throws Exception {
// check for existing data and writing
Integer key = new Integer(0);
String val = (String) map.get(key);
if (val == null) {
map.put(new Integer(10), “Second”);
}
//Reading Data
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
//Process the entry
}
}
}
TransWorker implements TransactionWorker which makes it necessary to implement the doWork method. This method is called by TransactionRunner when we pass an object of TransWorker to its run method. The TransWorker constructor simply receive an Environment object and construct other required objects . Then it opens the database in Collection mode, creates the required binding for the key and values we want to store in the database and finally it creates the SortedMap object which we can use to put and retrieve objects using it. Now let’s see the driver code which put this class in action.
public class CollectionSample {
public static void main(String[] argv)
throws Exception {
// Creating the environment
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTransactional(true);
envConfig.setAllowCreate(true);
Environment dbEnv = new Environment(new File(“/home/
masoud/dben-col”), envConfig);
// creating an instance of our TransactionWorker
TransWorker worker = new TransWorker(dbEnv);
TransactionRunner runner = new TransactionRunner(dbEnv);
runner.run(worker);
}
}
The steps demonstrated in the CollectionSample are self describing. The only new object in this snippet is the TransactionRunner object which we used to run the TransWorker object. I omit many of the safe programming portions to keep the code simple and conscious. we need exception handling and properly closure of all BDB JE objects to ensure data integrity
BDB JE Backup/Recovery and Tuning
Backup and Recovery
We can simply backup the BDB databases by creating an operating system level copy of all jdb files. When required we can put the archived files back into the environment directory to get a database back to the state it was at. The best option is to make sure all transactions and the write process are finished to have a consistent backup of the database.
The BDB JE provides a helper class located at com.sleepycat. je.util.DbBackup to perform the backup process from within a Java application. This utility class can create an incremental backup of a database and later on can restore from that backup. The helper class ideally freezes the BDB JE activities during the backup to ensure that the created backup exactly represents the database state when the backup process started.
Tuning
Berkeley DB JE has 3 daemon threads and configuring these threads affects the overall application performance and behavior. These 3 threads are as follow:
| Cleaner Thread | Responsible for cleaning and deleting unused log files. This thread is run only if the environment is opened for write access. |
| Checkpointer Thread | Basically keeps the BTree shape consistent. Checkpointer thread is triggered when environment opens, environment closes, and database log file grows by some certain amount. |
| Compressor Thread | For cleaning the BTree structure from unused nodes. |
These threads can be configured through a properties file named je.properties or by using the EnvironmentConfig and EnvironmentMutableConfig objects. The je.properties file, which is a simple key-value file, should be placed inside the environment directory and override any further configuration which we may make using the EnvironmentConfig and EnvironmentMutableConfig in the Java code.
The other performance effective factor is cache size. For ondisk instances cache size determines how often the application needs to refer to permanent storage in order to retrieve some data bucket. When we use in-memory instances cache size determines whether our database information will be paged into swap space or it will stay in the main memory.
| je.cleaner.minUtilization | Ensures that a minimum amount of space is occupied by live records by removing obsolete records. Default occupied percentage is 50%. |
| je.cleaner.expunge | Determines the cleaner behavior in the event that it is able to remove an entire log file. If “true” the log file will be deleted, otherwise it will be renamed to nnnnnnnn.del |
| je.checkpointer.bytesInterval | Determines how often the Checkpointer should check the BTree structure. If it performs the checks little by little it will ensure a faster application startup but will consume more resources specially IO. |
| je.maxMemory Percent | Determines what percentage of JVM maximum memory size can be used for BDB JE cache. To determine the ideal cache size we should put the application in the production environment and monitor its behavior. |
A complete list of all configurable properties, with explanations, is available in EnvironmentConfig Javadoc. The list is comprehensive and allows us to configure the BDB JE at granular level.
All of these parameters can be set from Java code using the EnvironmentConfig object. The properties file overrides the values set by using EnvironmentConfig object.
Helper Utilities
Three command line utilities are provided to facilitate dumping the databases from one environment, verifying the database structure, and loading the dump into another environment.
| DbDump | Dumps a database to a user-readable format. |
| DbLoad | Loads a database from the DbDump output. |
| DbVerify | Verifies the structure of a database. |
To run each of these utilities, switch to BDB JE directory, switch to lib directory and execute as shown in the following command:
java -cp je-3.3.75.jar com.sleepycat.je.util.DbVerify
The JAR file name may differ depending on your version of BDB JE. These commands can also be used to port a BDB JE database to BDB Core Edition.

Getting Started with Selenium
By Frank Cohen
21,525 Downloads · Refcard 67 of 187 (see them all)
Download
FREE PDF
The Essential Selenium Cheat Sheet
Getting Started with Selenium
About Selenium
Selenium is a portable software testing framework for Web applications. Selenium works well for QA testers needing record/playback authoring of tests and for software developers needing to author tests in Java, Ruby, Python, PHP, and several other languages using the Selenium API. The Selenium architecture runs tests directly in most modern Web browsers, including MS IE, Firefox, Opera, Safari, and Chrome. Selenium deploys on Windows, Linux, and Macintosh platforms.
Selenium was developed by a team of programmers and testers at ThoughtWorks. Selenium is open source software, released under the Apache 2.0 license and can be downloaded and used without royalty to the originators.
Architecture in a Nutshell
Selenium Browserbot is a JavaScript class that runs within a hidden frame within a browser window. The Browserbot runs your Web application within a sub-frame. The Browserbot receives commands to operate against your Web application, including commands to open a page, type characters into form fields, and click buttons.
Selenium architecture offers several ways to play a test.

Functional testing (Type 1) uses the Selenium IDE add-on to Firefox to record and playback Selenium tests in Firefox. Functional testing (Type 2) uses Selenium Grid to run tests in a farm of browsers and operating environments. For example, run install Selenium Grid on 3 operation environments (for example, Windows Vista, Windows XP, and Ubutu) and on each install 2 browser (for example, Microsoft Internet Explorer and Firefox) to smoke test, integration test, and functional test your application on 6 combinations of operating environment and browser. Many more combinations of operating environment and browser are possible. An option for functional testing (Type 2) is to use the PushToTest TestMaker/TestNode open source project. It uses Selenium RC to provide Selenium Gridlike capability with the added advantage of providing datadriven Selenium tests, results analysis charts and graphs, and better stability of the test operations.
The PushToTest open-source project provides Selenium datadriven testing, load testing, service monitoring, and reporting. TestMaker runs load and performance tests (Type 3) in a PushToTest TestNode using the PushToTest SeleniumHTMLUnit library and HTMLUnit Web browser (and Rhino JavaScript engine.)

HTMLUnit runs Selenium tests faster than a real browser and requires much less memory and CPU resources.
Installing selenium
Selenium IDE installs as a Firefox add-on. Below are the steps to download and install Selenium IDE:
- Download selenium-ide-1.0.2.xpi (or similar) from http://seleniumhq.org.
- From Firefox open the .xpi file. Follow the Firefox instructions.
- Note: Selenium Grid runs as an Ant task. You need JDK 1.6, Ant 1.7, and the Selenium Grid 1.0 binary distribution. Additional directions can be found at http://selenium-grid.seleniumhq.org/get_started.html
- See http://www.pushtotest.com/products for TestMaker installation instructions.
Record/playback using selenium ide

Selenium IDE is a Firefox add-on that records clicks, typing, and other actions to make a test, which you can play back in the Firefox browser. Open Selenium IDE from the Firefox Tools drop-down menu, Selenium IDE command.


Selenium IDE records interactions with the Web application, with one command per line. Clicking a recorded command highlights the command, displays a reference page, and displays the command in a command form editor. Click the command form entry down-triangle to see a list of all the Selenium commands.
Run the current test by clicking the Run Test Case icon in the icon bar. Right click a test command to choose the Set Breakpoint command. Selenium IDE runs the test to a breakpoint and then pauses. The icon bar Step icon continues executing the test one command at a time.
With Selenium IDE open, the menu bar context changes to provide access to Selenium commands: Open/Close Test Case and Test Suite. Test Suites contain one or more Test Cases.
Use the Options dropdown menu, Options command to set general preferences for Selenium IDE.
Selenium IDE provides an extensibility API set called User Extensions. You can implement custom functions and modify Selenium IDE behavior by writing JavaScript functions. We do not recommend writing User Extensions as the Selenium project makes no guarantees to be backwardly compatible from one version to the next.
Selenium Context Menu provides quick commands to insert new Selenium commands, evaluate XPath expressions within the live Web page, and to show all available Selenium commands. Right click on commands in Selenium IDE, and right-click on elements in the browser page to view the Selenium Context Menu commands.
Selenese Table Format
Selenium IDE is meant to be a light-weight record/playback tool to facilitate getting started with Selenium. It is not designed to be a full test development environment. While Selenium records in an HTML table format (named Selenese) the table format only handles simple procedural test use cases. The Selenese table format does not provide operational test data support, conditionals, branching, and looping. For these you must Export Selenese files into Java, Ruby, or other supported languages.
Selenium Command reference
Selenium comes with commands to: control Selenium test operations, browser and cookie operations, pop-up, button, list, edit field, keyboard, mouse, and form operations. Selenium also provides access operations to examine the Web application (details are at http://release.seleniumhq.org/selenium-core/0.8.0/reference.html).
| Command | Value, Target, Wait Command |
| Selenium Control | |
| setTimeout | milliseconds |
| setMouseSpeed | number of pixels |
| setMouseSpeedAndWait | |
| setSpeed | milliseconds |
| setSpeedAndWait | |
| addLocationStrategy | strategyName |
| addLocationStrategyAndWait | |
| allowNativeXpath | boolean |
| allowNativeXpathAndWait | |
| ignoreAttributesWithoutValue | boolean |
| ignoreAttributesWithoutValueAndWait | |
| assignId | locator |
| assignIdAndWait | |
| captureEntirePageScreenShot | filename, kwargs |
| captureEntirePageScreenShotAndWait | |
| echo | message |
| pause | milliseconds |
| runScript | javascript |
| runScriptAndWait | |
| waitForCondition | javascript |
| waitForPageToLoad | milliseconds |
| waitForPopUp | windowID |
| fireEvent | locator |
| fireEventAndWait | |
| Browser Operations | |
| open | url |
| openAndWait | |
| openWindow | url |
| openWindowAndWait | |
| goBack | goBackAndWait |
| refresh | refreshAndWait |
| close | |
| deleteCookie | name |
| deleteCookieAndWait | |
| deleteAllVisibleCookies | deleteAllVisibleCookiesAndWait |
| setBrowserLogLevel | logLevel |
| setBrowserLogLevelAndWait | |
| Cookie Operations | |
| createCookie | nameValuePair |
| createCookieAndWait | |
| deleteCookie | name |
| deleteCookieAndWait | |
| deleteAllVisibleCookies | deleteAllVisibleCookiesAndWait |
| Popup Box Operations | |
| answerOnNextPrompt | answer |
| answerOnNextPromptAndWait | |
| chooseCancelOnNextConfirmation | chooseCancelOnNextConfirmationAndWait |
| chooseOkOnNextConfirmation | chooseOkOnNextConfirmationAndWait |
| Checkbox & Radio Buttons | |
| check | locator |
| checkAndWait | |
| uncheck | locator |
| uncheckAndWait | |
| Lists & Dropdowns | |
| addSelection | locator |
| addSelectionAndWait | |
| removeSelection | removeSelectionAndWait |
| removeAllSelections | removeAllSelectionsAndWait |
| Edit Fields | |
| type | locator |
| typeAndWait | |
| typeKeys | locator |
| typeKeysAndWait | |
| setCursorPosition | locator |
| setCursorPositionAndWait | |
| Keyboard Operations | |
| keyDown | locator |
| keyDownAndWait | |
| keyPress | locator |
| keyPressAndWait | |
| keyUp | locator |
| keyUpAndWait | |
| altKeyDown | altKeyDownAndWait |
| altKeyUp | altKeyUpAndWait |
| controlKeyDown | controlKeyDownAndWait |
| controlKeyUp | controlKeyUpAndWait |
| metaKeyDown | metaKeyDownAndWait |
| metaKeyUp | metaKeyUpAndWait |
| shiftKeyDown | shiftKeyDownAndWait |
| shiftKeyUp | shiftKeyUpAndWait |
| Mouse Operations | |
| click | locator |
| clickAndWait | |
| clickAt | locator |
| clickAtAndWait | |
| doubleClick | locator |
| doubleClickAndWait | |
| doubleClickAt | locator |
| doubleClickAtAndWait | |
| contextMenu | locator |
| contextMenuAndWait | |
| contextMenuAt | locator |
| contextMenuAtAndWait | |
| mouseDown | locator |
| mouseDownAndWait | |
| mouseDownA | locator |
| mouseDownAtAndWait | |
| mouseMove | locator |
| mouseMoveAndWait | |
| mouseMoveAt | locator |
| mouseMoveAtAndWait | |
| mouseOut | locator |
| mouseOutAndWait | |
| mouseOver | locator |
| mouseOverAndWait | |
| mouseUp | locator |
| mouseUpAndWait | |
| mouseUpAt | locator |
| mouseUpAtAndWait | |
| dragAndDrop | locator |
| dragAndDropAndWait | |
| dragAndDropToObject | sourceLocator |
| dragAndDropToObjectAndWait | |
| Form Operations | |
| submit | formLocator |
| submitAndWait | |
| Windows/Element Selection | |
| select | locator |
| selectAndWait | |
| selectFrame | locator |
| selectWindow | windowID |
| focus | locator |
| focusAndWait | |
| highlight | locator |
| highlightAndWait | |
| windowFocus | windowFocusAndWait |
| windowMaximize | windowMaximizeAndWait |
Selenese Table Format
Selenium commands identify elements within a Web page using:
| identifier=id | Select the element with the specified @id attribute. If no match is found, select the first element whose @name attribute is id. |
| name=name | Select the first element with the specified @name attribute. The name may optionally be followed by one or more elementfilters, separated from the name by whitespace. If the filterType is not specified, value is assumed. For example, name=style value=carol |
| dom=javascriptExpression | Find an element using JavaScript traversal of the HTML Document Object Model. DOM locators must begin with "document." For example: dom=document.forms['form1'].myList dom=document.images[1] |
| xpath=xpathExpression |
Locate an element using an XPath expression. Here are a few examples:
|
| link=textPattern | Select the link (anchor) element which contains text matching the specified pattern. |
| css=cssSelectorSyntax |
Select the element using css selectors. For example:
Selenium 1.0 css selector locator supports all css1, css2 and css3 selectors except namespace in css3, some pseudo classes(:nthof-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type, :visited, :hover, :active, :focus, :indeterminate) and pseudo elements(::first-line, ::first-letter, ::selection, ::before, ::after). Without an explicit locator prefix, Selenium uses the following default strategies: dom, for locators starting with "document." xpath, for locators starting with "//" identifier, otherwise |
Your choice of element locator type has an impact on the test playback performance. The following table compares performance of Selenium element locators using Firefox 3 and Internet Explorer 7.
| Locator used | Type | Firefox 3 | Internet Explorer 7 |
| q | Locator | 47 ms | 798 ms |
| //input[@name='q'] | XPath | 32 ms | 563 ms |
| //html[1]/body[1]//form[1]//input[2] | XPath | 47 ms | 859 ms |
| //input[2] | XPath | 31 ms | 564 ms |
| document.forms[0].elements[1] | DOM Index | 31 ms | 125 ms |
Additional details on Selenium performance can be found at: http://www.pushtotest.com/docs/thecohenblog/symposium
Script-Driven Testing
Selenium implements a domain specific language (DSL) for testing. Some applications do not lend themselves to record/ playback: 1) The test flow changes depending on the results of a step in the test, 2) The input data changes depending on the state of the application, and 3) The test requires asynchronously operating test flows. For these conditions, consider using the Selenium DSL in a script driven test. Selenium provides support for Java, Python, Ruby, Groovy, PHP, and C#.
Selenium IDE helps get a script-driven test started by exporting to a unit test format. For example, consider the following test in the Selenese table format:

Use the Selenium IDE File menu, Export, Python Selenium RC command to export the test to a jUnit-style TestCase written in Python. The following shows the Java source code:
package com.example.tests;
from selenium import selenium
import unittest, time, re
class franktest(unittest.TestCase):
def setUp(self):
self.verificationErrors = []
self.selenium = selenium("localhost", 4444, "*chrome", \
"http://change-this-to-the-site-you-are-testing/")
self.selenium.start()
def test_franktest(self):
sel = self.selenium
sel.open("/")
sel.type("q", "sock puppet")
sel.click("sa")
sel.wait_for_page_to_load("30000")
sel.click("//div[@id='res']/div[1]/ol/li[1]/div/h2/a/em")
sel.click("//div[@id='res']/div[1]/ol/li[1]/div/h2/a/em")
sel.wait_for_page_to_load("30000")
def tearDown(self):
self.selenium.stop()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
An exported test like the one above has access to all of Python's functions, including conditionals, looping and branching, reusable object libraries, inheritance, collections, and dynamically typed data formats.
Selenium provides a Selenium RC client package for Java, Python, C#, Ruby, Groovy, PHP, and Perl. The client object identifies the Selenium RC service in its constructor:
self.selenium = selenium("localhost", 4444, "*iexplore", \
"http://change-this-to-the-site-you-are-testing/")
self.selenium.start()
The above code identifies the Selenium RC service running on the localhost machine at port 4444. This client will run the test in Microsoft Internet Explorer. The third parameter identifies the base URL from which the recorded test will operate.

Using the selenium.start() command initializes and starts the Selenium RC service. The Selenium RC client module (import selenium in Python) provides methods to operate the Selenium DSL commands (click, type, etc.) in the Browserbot running in the browser. For example, selenium.click("open") tells the Browserbot to a click command to the element with an id tag equal to "open". The browser responds to the click command and communicates with the Web application.
At the end of the test the selenium.stop() command ends the Selenium RC service.
Selenium and Ajax
Ajax uses asynchronous JavaScript functions to manipulate the browser's DOM representation of the Web page. Many Selenium commands are not compatible with Ajax. For example, ClickAndWait will time-out waiting for the browser to load the Web page because Ajax functions that manipulate the current Web page in response to a click event do not reload the page. We recommend using Selenium commands that poll the DOM until the Ajax methods complete their tasks. For example, waitUntilElementPresent polls the DOM until the JavaScript function adds the desired element to the page before continuing with the rest of the Selenium script.
Consider the following checklist when using Selenium with Ajax applications:
|
|
Your Selenium tests may require a large number of extra commands to ensure the test stays in synchronization with the Ajax application. Consider an Ajax application that requires a log-in, then displays a selection list of items, then presents an order form. Ajax enabled applications often deliver multiple steps of function on a single page and show-and-hide elements as you work with the application. Some even disable form submit buttons and other user interface elements until you enter enough valid information. For an application like this you will need a combination of Selenium commands. Consider the following Selenium test: waitForElementPresent pauses the test until the Ajax application adds the requisite element to the page. waitForCondition pauses the test until the JavaScript function evaluates to true. |
|
|
Some Ajax applications use lazy-loading techniques to improve user interaction with the application. A stock market application provides a list of 10 stock quotes asynchronously after the user clicks the submit button. The list may take 10 to 50 seconds to completly update on the screen. Using waitForXPathCount pauses the test until the page contains the number of nodes that match the specified XPath expression. |
|
|
Many Ajax applications use dynamic element id tags. The Ajax application that named the Log-out button app_6 may later rename the button to app_182. We recommend using DOM element locator techniques, or XPath techniques if needed, to dynamically find elements on a positional or other attribute means. |

Working with tinymce and Ajax objects
Ajax is about moving functions off the server and into the browser. Selenium architecture supports innovative new browser-based functions because Selenium's Browserbot is a JavaScript class itself. The Browserbot even lets Selenium tests operate JavaScript functions as part of the test. For example, TinyMCE (http://tinymce.moxiecode.com) is a graphical text editor component for embedding in Web pages. TinyMCE supports styled text and what-you-see-is-what-you-get editing. Testing a TinyMCE can be challenging. Selenium offers click and type functions that interact with TinyMCE but no direct commands for TinyMCE's more advanced functions. For example, imagine testing TinyMCE's ability to stylize text. The test needs to insert test, move the insertion point, select a sentence, bold the text, and drag the sentence to another paragraph. This is beyond Selenium's DSL. Instead, the Selenium test may include JavaScript commands that interact with TinyMCE's published API (http://tinymce.moxiecode.com/documentation.php).
Here is an example of using the TinyMCE API from a Selenium test context:
this.browserbot.getCurrentWindow().tinyMCE.execCommand
('mceInsertContent',false,'<b>Hello world!!</b>');
Run the above JavaScript function from within a Selenium test using the AssertEval command.
AssertEval javascript:this.browserbot.getCurrentWindow().tinyMCE.
execCommand('mceInsertContent',false,'<b>Hello world!!</b>');
Data Production
Selenium offers no operational test data production capability itself. For example, a Selenium test of a sign-in page usually needs sign-in name and sign-in password operational test data to operate. Two options are available: 1) Use the data access features in Java, Ruby, or one of other supported languages, 2) Use PushToTest TestMaker's Selenium Script Runner to inject data from comma separated value (CSV) files, relational databases, objects, and Web services. See http://tinyurl.com/btxvn4 for details.
Create a Comma-Separated-Value file. Use your favorite text editor or spreadsheet program. Name the file data.csv. The contents must be in the following form.

The first row of the data file contains column names. These will be used to map values into the Selenium test. Change the Selenium test to refer to mapping name. PushToTest maps the data from the named column in the CSV data file to the Selenium test data using the first row definitions.
Connect the Data Production Library (DPL) to the Selenium test in a TestMaker TestScenario. Begin by definition a HashDPL. This DPL reads from CSV data files and provides the data to the test.
<DataSources>
<dpl name="mydpl" type="HashDPL">
<argument name="file" dpl="rsc" value="getDataByIndex" index="0"/>
</dpl>
</DataSources>
Next, tell the TestScenario to send the data.csv and Selenium test files to the TestNodes that will operate the test.
<resources>
<data path="data.csv"/>
<selenese path="CalendarTest.selenium"/>
</resources>
Then tell the Selenium ScriptRunner to use the DPL provided data when running the Selenium test.
<run name="CalendarTest" testclass="CalendarTest.selenium"
method="runSeleneseFile" langtype="selenium">
<argument dpl="mydpl" name="DPL_Properties" value="getNextData"/>
</run>
The getNextData operation gets the next row of data from the CSV file. The Selenium ScriptRunner injexts the data into the Selenium test.
Browser Sandbox, Redirect, and proxy issues
Selenium RC launches the browser with itself as the proxy server to inject the Javascript of the Browserbot and your test. This architecture makes it possible to run the same test on multiple browsers. However, some browsers will warn the user of possible security threats when the proxy starts and when the test requests functions or pages outside of the originating domain. The browser takes control and stops the Browserbot operations to display the warning message. When this happens, the test stops until a user dismisses the warning. There are no reliable cross-browser workarounds.
Some Web applications redirect from http to https URLs. The browser will often issue a warning that stops the Selenium test.
Selnium does not support a test moving across domains. For example, a test that started with a baseurl of www.mydomain. com may not open a page on www.secondomain.com.
selenium RC browser profiles
Selenium Remote Control (RC) enables test operation on multiple real browsers. A browser profile attribute may be any of the following installed browsers: chrome, konqueror, piiexplore, iehta, mock, opera, pifirefox, safari, iexplore and custom. Append the path to the real browser after browser profile if your system path does not state the path to the browser. For example:
*firefox /Applications/Firefox.app/Contents/MacOS/firefox
Component approach example
Many organizations pursue a "Test and Trash" methodology to achieve agile software development lifecycles. For example, an organization in pursuit of agile techniques may change up to 30% of an application with an application lifecycle of 8 weeks. Without giving the change much thought, up to 30% of their recorded tests break!

We recommend a component approach to building tests. Test components perform specific test operations. We write or record tests as individuals components of test function. For example, a component operates the sign-in function of a private Web application. When the sign-in portion of the application changes, we only need to change the sign-in test and the rest of test continues to perform normally.
Selenium supports the component approach in three ways: Selenium IDE supports Test Suites and Test Cases, exporting Selenium tests to dynamic languages (Java, Ruby, Perl, etc.) creates reusable software classes, and 3) PushToTest TestMaker supports multiple use cases with parameterized test use cases.
In Selenium IDE, the File menu enables tests to be saved as test cases or test suites. Record a test, use File -> Save Test Case. Create a second Test Case by choosing File -> New Test Case. Record the second test use case. Save the TestSuite for these two test use cases by choosing File -> Save TestSuite. Click the "Run entire test suite" icon from the Selenium IDE tool bar.
TestMaker defines test use cases using a simple XML notation:
<usecases>
<usecase name="MailerCheck_usecase">
<test>
<run name="LogIn" testclass="Login.selenium" instance="myinst"
method="runSeleneseFile" langtype="selenium">
</run>
<run name="OrderProduct" testclass="OrderProduct.selenium" instance="myinst"
method="runSeleneseFile" langtype="selenium">
</run>
</test>
</usecase>
</usecases>
Reporting options
Selenium offers no results reporting capability of its own. Two options are available: 1) Write your tests as a set of JUnit tests and use JUnit Report (http://ant.apache.org/manual/OptionalTasks/junitreport.html) to plot success/failure charts, 2) Use PushToTest TestMaker Results Analysis Engine to produce more than 300 charts from the transaction and step time tracking of Selenium tests.
For example, TestMaker tracks Selenium command duration in a test suite or test case. Consider the following chart. This shows the "Step" time it takes to process each Selenium command in a test use case over 10 equal periods of time that the test took to operate.

Selenium Biosphere
Test Maker allows repurposing Selenium tests as load test service monitors. http://www.pushtotest.com
BrowserMob facilitates low-cost Selenium load testing. http://browsermob.com/load-testing
SauceLabs provides a farm of Selenium RC servers for testing. http://saucelabs.com/
ThoughtWorks Twist can be used for test authoring and management. http://studios.thoughtworks.com/twist-agile-test-automation
Running a Selenium test as a functional test in TestMaker. TestMaker displays the success/failure of each command in the test and the duration in milliseconds of each step.
The Future, Selenium 2.0 (AKA Webdriver )
The Selenium Project started the WebDriver project, to be delivered as Selenium 2.0. WebDriver is a new architecture that plays Selenium tests by driving the browser through its native interface. This solves the test playback stability issue in Selenium 1.0 but requires the Selenium project to maintain individual API drivers for all the supported browsers. While there is no release date for Selenium 2.0, the WebDriver code is already functional and available for download at http://code.google.com/p/webdriver.
Available Training
SkillsMatter.com, Think88com, PushToTest.com, RTTSWeb.com, and Scott Bellware (http://blog.scottbellware.com) offer training courses fro Selenium. PushToTest offers free Open Source Test Workshops (http://workshop.pushtotest.com) as a meet-up for Selenium and other Open Source Test tool users.
About The name Selenium
Selenium lore has it that the originators chose the name of Selenium after learning that Selenium is the antidote to Mercury poisoning. There appears to be no love between the Selenium team and HP Mercury, but perhaps a bit of envy
Getting Started with ServiceMix 4.0
By
9,484 Downloads · Refcard of 187 (see them all)
Download
FREE PDF
The Essential Getting Started with ServiceMix 4.0 Cheat Sheet
Getting Started with Eclipse RCP
By James Sugrue
18,134 Downloads · Refcard 62 of 187 (see them all)
Download
FREE PDF
The Essential Eclipse RCP Cheat Sheet
Getting Started with Eclipse RCP
About the Rich client platform
The Eclipse Rich Client Platform (RCP) is a platform for building and deploying rich client applications. It includes Equinox, a component framework based on the OSGi standard, the ability to deploy native GUI applications to a variety of desktop operating systems, and an integrated update mechanism for deploying desktop applications from a central server. Using the RCP you can integrate with the Eclipse environment, or can deploy your own standalone rich application.
Introducing the Plug-in development environment
To get started in developing your own plug-ins, first download a version of Eclipse including the Plug-in Development Environment (PDE). Eclipse Classic is the best distribution for this.
When developing plug-ins, you should use the Plug-in Development perspective. You'll notice this perspective provides another tab in your Project Navigator listing all the plug-ins available.
To create an RCP application, go to the File menu and select New > Project where you will be presented with the new project wizard. From here choose Plug-in Project.

Figure 1: The New Project Wizard
The next screen allows you to assign a name to your plugin. Usually, plug-in name follow Java's package naming conventions. RCP applications should be targeted to run on a particular version of Eclipse, here we choose to run on Eclipse 3.5.

Figure 2: RCP Project Settings Page
The next page in the project wizard allows you to set some important attributes of your plug-in. This page allows you to specify whether your plug-in will make contributions to the UI. In the case of RCP plug-ins, this will usually be true. You can choose whether to create your own RCP application, or to create a plug-in that can be integrated with existing Eclipse installations.
The following table summarizes other plug-in settings and what they mean for your application. All of these settings can be changed in the generated MANIFEST.MF file for your project at any stage.
| Attribute Name | Default Value | Meaning |
| id | <project name> | The identifier for this RCP plug-in |
| Version | 1.0.0.qualifier | The plug-in version. Multiple versions of any plug-in are possible in your Eclipse environment provided they have unique version numbers |
| Name | RCP Application | The readable name of this plug-in |
| Provider | The second part of your project package name. | The provider of this plug-in |

Get started quickly with your first RCP application by using the included RCP Mail Template, available when you choose to create a standalone RCP application.
Manifest.mf explained
The generated META-INF/MANIFEST.MF file is the centre of your RCP plug-in. Here you can define the attributes, dependencies and extension points related to your project. In addition, you may have a plugin.xml file. The contents of both these files are show in the plug-in manifest editor.

Figure 3: The plug-in manifest editor
The Overview tab in this editor allows you to change the settings described earlier in the new project wizard. It also provides a shortcut where you can launch an Eclipse application containing your new RCP plug-in.
The Dependencies tab describes how this plug-in interacts with others in the system. All plug-ins which you are dependent on will need to be added here.
The Runtime tab allows you to contribute packages from your own plug-in to others to use or extend. You can also add libraries that don't exist as plug-ins to your own project in the Classpath section.

While you may change your build path through the Dependencies or Runtime tab, changing dependent plug-ins in the Java Build Path of the project properties tab will not reflect properly in the plug-ins manifest.
The Extensions tab is where you go to define how this plug-in builds on the functionality of other plug-ins in the system, such as for adding menus, views or actions. We will describe these extension points in more detail in the relevant sections. The Extension Points tab allows you to define your own extensions for other plug-ins to use.
The Standar d Widget Toolkit and Jface
While developing UI code for your RCP application, it is important to understand the Standard Widget Toolkit (SWT). This is a layer that wraps around the platform's native controls. JFace provides viewers, in a similar way to Swing, for displaying your data in list, tables, tree and text viewers.
The UI toolkits used in Eclipse applications are a large topic, so we assume that the reader will be aware of how to program widgets in SWT and JFace.
Adding a menu to your plug-in
One of the first things that you will want to do with your RCP plug-in is to provide a menu, establishing its existence with the Eclipse application that it is built into. To do this, as with any additions to our plug-in, we start in the Extensions tab of the plug-in manifest editor.
Up to Eclipse 3.3 Actions was the only API available to deal with menus, but since then the commands API has become available, which we will focus on here.
To add a menu in the command API you will need to follow similar steps to these:
Declare a command
To do this we use the org.eclipse.ui.commands extension point. Simply click on the Add... button in the Extensions tab and chose the relevant extension point.
First, you will need to associate this command with a category. Categories are useful for managing large numbers of commands. From the org.eclipse.ui.commands node, select New > Category. The required fields are a unique ID and a readable name.
After this right click on the node and choose New>Command. The important attributes for a command are listed below.
| Attribute Name | Required | Use |
| id | Yes | A unique id for this command |
| Name | Yes | A readable name for the command |
| Description | No | A short description for display in the UI |
| CategoryID | No | The id of the category for this command (that you described in the previous step). |
| DefaultHandler | No | A default handler for this command. Usually you will create your own handler. |
Declare a Menu Contribution for the Command
To create a menu, you will first need to add the org.eclipse. ui.menus extension point. From the created node in the UI, select New>menuContribution. The required attribute for the menu contribution is it's locationURI, which specifies where the menu should be placed in the UI. This URI takes the format of [scheme]:[id]?[argument-list]
An example of the more useful locationURI's in the Eclipse platform follow:
| Attribute Name | Required |
|
menu:org.eclipse.ui.main.
menu?after=window |
Insert this contribution on the main menu bar after the Window menu |
| menu:file?after=additions | Inserts contribution in the File menu after the additions group |
|
toolbar:org.eclipse.ui.main.
toolbar?after=additions |
Insert this contribution on the main toolbar |
|
popup:org.eclipse.ui.popup.
any?after=additions |
Adds this contribution to any popup menu in the application |
Once the location of your contribution is chosen, click on New>command on this contribution to define the menu. The following attributes exist for each command:
| Attribute | Required | Use |
| commandId | Yes | The id of the Command object to bind to this element, typically already defined, as in our earlier step. Click Browse... to find this |
| Label | No | The readable label to be displayed for this menu item in the user interface |
| id | No | A unique identifier fo this item. Further menu contributions can be placed under this menu item using this id in the locationURI |
| mnemonic | No | The Character within the label to be assigned as the mnemonic |
| icon | No | Relative path to the icon that will be displayed to the left of the label |
| tooltip | No | The tooltip to display for this menu item |

Defining a toolbar item is a similar process. Based on a menuContribution with the correct locationURI, select New>Toolbar providing a unique id. Create a new command under the toolbar similar to the menu item approach.
Create a Handler for the Command
The final extension point required for the menu is org.eclipse. ui.handlers. A handler has two vital attributes. The first is the commandId which should be the same as the command id specified in the beginning. As you can see, this is the glue between all three parts of the menu definition.
You will also need to create a concrete class for this handler, which should implement the org.eclipse.core.commands. IHandler interface.

Clicking on the class hyperlink on the manifest editor will pop up a New Class Wizard with the fields autofilled for this.
Finally, you will need to define when this command is enabled or active. This can be done programmatically in the isEnabled() and isHandled() methods. While this is easiest, the recommended approach is to use the activeWhen and enabledWhen expressions in the plug-ins manifest editor which avoids unnecessary plug-in loading.

Once you have added in an extension point plugin. xml will become available. All extension points can be added through the manifest editor, or in XML format through this file.
Views
In an RCP applications Views are used to present information to the user. A viewer must implement the org.eclipse. ui.IViewPart interface, or subclass org.eclipse.ui.parts.ViewPart.

Figure 4: An illustration of the difference between perspective, editor and view.
To create a View, you will need to add the org.eclipse. ui.views extension point. In order to group your views, it is useful to create a category for them. Select New>Category from the org.eclipse.ui.views node to do this. The required fields are a unique ID and a readable name.
Next, choose New>View from the extension point node and fill in the necessary details.
| Attribute | Required | Use |
| id | Yes | The unique id of the View |
| name | Yes | A readable name for this view |
| class | Yes | The class that implements the IViewPart interface |
| category | No | The id of the category that contains this view. This category should be used if you wish to group views together in the Show Views... dialog. |
| icon | No | The image to be displayed in the top left hand corner of the view |
| allowMultiple | No | Flag indicating whether multiple views can be instantiated. The default value is false. |
The code behind the view is in a class that extends org.eclipse.ui.ViewPart. All controls are created programmatically In the createPartControl() method in this class.
To facilitate lazy loading, a workbench page only holds IViewReference objects, so that you can list out the views without loading the plug-in that contains the view definition.
When created, you will see your view in the Window>Show View>Other... dialog

It's good practice to store the view's id as a public constant in your ViewPart implementation, for easy access.
Loose Coupling
To facilitate loose coupling, your ViewPart should implement org.eclipse.ui.ISelectionListener. You will also need to register this as a selection listener for the entire workbench:
getSite().getWorkbenchWindow().getSelectionService().
addSelectionListener(this);
This allows your view to react to selections made outside of the view's own context.
Editors
An editor is used in an Eclipse RCP application when you want to create or modify files, or other resources. Eclipse already provides some basic text and Java source file editors.
In your plug-in manifest editor, add in the org.eclipse. ui.editors extension point, and fill in the following details
| Attribute | Required | Use |
| id | Yes | The unique id of this editor |
| name | Yes | A readable name for this editor |
| icon | No | The image to be displayed in the top left hand corner of the editor when it is open |
| extensions | No | A string of comma separated file extensions that are understood by the editor |
| class | No | The class that implements the IEditorPart interface |
| command | No | A command to run to launch and external editor |
| launcher | No | The name of a class that implements IEditorLauncher to an external editor |
| contributorClass | No | A class that implements IEditorActionBarContributor and adds new actions to the workbench menu and toolbar which reflect the features of the editor type |
| default | No | If true this editor will be used as the default for this file type. The default value is false |
| filenames | No | A list of filenames understood by the editor. More specific than the extensions attribute |
| matchingStrategy | No | An implementation of IEditorMatchingStrategy that allows an editor to determine whether a given editor input should be opened |
Editors implement the org.eclipse.ui.IEditorPart interface, or subclass org.eclipse.ui.parts.EditorPart.
Like views, to facilitate lazy loading, a workbench page only holds IEditorReference objects, so that you can list out the editors without loading the plug-in that contains the editor definition.
Perspectives
Perspectives are a way of grouping you views and editors together in a way that makes sense to a particular context, such as debugging. By creating your own perspective, you can hook into the Window>Open Perspective dialog.
To create a perspective, you need to extend the org.eclipse.ui.perspectives extension point.
| Attribute | Required | Use |
| id | Yes | The unique id of this perspective |
| name | Yes | A readable name for the perspective |
| class | Yes | The class that implements the IPerspectiveFactory interface |
| icon | No | The image to be displayed related to this perspective |
| Fixed | No | Whether this perspective can be closed or not. Default is false |
The class driving the perspective implements org.eclipse. ui.IPerspectiveFactory. This class has one method createInitialLayout(), within which you can use the IPageLayout.addView() method to add views directly to the perspective. To group many views together in a tabbed fashion, rather than side by side, IPageLayout.createFolder() can be used.

When running your application you need to ensure that you have all required plug-ins included. Do this by checking your Run Configurations. Go to the plugins tab and click Validate Plug-ins. If there are errors click on Add Required Plug-ins to fix the error.
Preferences
Now that you have created a perspective and a view for your RCP application, you will probably want to provide some preference pages. Your contributed preference pages will appear in the Window>Preferences dialog.
To provide preference pages you will need to implement the org.eclipse.ui.preferencePages extension in the plug-in manifest editor.
| Attribute | Required | Use |
| id | Yes | The unique id of this preference page |
| name | Yes | A readable name for the preference page |
| class | Yes | The class that implements the IWorkbenchPreferencePage interface |
| category | No | Path indicating the location of the page in the preferences tree. The path may be defined using the parent preference page id or a sequence of ids separated by "/". If no category is specified, the page will appear at the top level of the preferences tree. |
While the preference page class will implement org.eclipse. ui.IWorkbenchPreferencePage, it is useful to extend org. eclipse.jface.preference.FieldEditorPreferencePage as it provides createFieldEditors() method which is all you need to implement, along with the init() method in order to display a standard preference page. A complete list of FieldEditors is provided in the org.eclipse.jface.preference package.
Loading and Storing Preferences
Preferences for a plug-in are stored in an org.eclipse.jface. preference.IPreferenceStore object. You can access a plug-ins preference through the Activator, which will typically extend org.eclipse.ui.plugin.AbstractUIPlugin. Each preference you add to the store has to be assigned a key. Preferences are stored as String based values, but methods are provided to access the values in number of formats such as double, int and Boolean.
Property Sheets
While preferences are used to display the overall preferences for the plug-in, property sheets are used to display the properties for views, editors or other resources in the Eclipse environments. By hooking into the Properties API, the properties for you object will appear in the Properties view (usually displayed at the bottom of your Eclipse application).
The Properties view will check if the selected object in the workspace can supports the org.eclipse.ui.views. properties.IPropertySource interface, either through implementation or via the getAdapter() method of the object. Each property gets a descriptor and a value through the IPropertySource interface.
Help
All good applications should provide some level of user assistance. To add help content to the standard Help>Help Contents window, you can use the org.eclipse.help.toc extension point. Add a number of toc items to this extension point, the only mandatory attribute for each toc entry is the file that contains the table of contents definition.

To see a quick example of what help content should look like, choose the Help Content item from the Extension Wizards tab when adding to the plug-ins manifest.
<toc label="Getting Started" link_to="toc.xml#gettingstarted">
<topic label="Main Topic" href="html/gettingstarted/
maintopic.html">
<topic label="Sub Topic" href="html/gettingstarted/
subtopic.html" />
</topic>
<<topic label="Main Topic 2">
<topic label="Sub Topic 2" href="html/gettingstarted/
subtopic2.html" />
</topic>
</toc>
Each topic entry should have a link to a HTML file with the full content for that topic. The above XML extract from a table of contents file illustrates this. There is also the choice to use the definition editor for help content. This will open by default in Eclipse when choosing a toc file.
Cheat Sheets
Another user assistance mechanism used in Eclipse is a cheat sheet, which guides the user through a series of steps to achieve a task. To create your initial cheat sheet content, use the New>Other...>User Assistance>Cheat Sheet. This presents you with an editor to add an Intro and a series of items, with the option to hook in commands to automate the execution of the task.
To add this cheat sheet to your plug-in manifest, the cheat sheet editor has a Register this cheat sheet link on the top right hand corner. When registering the cheat sheet you will need to provide it with a category and a description.

Figure 5: Cheat sheet registration dialog
Clicking finish on this dialog will add the org.eclipse. ui.cheatsheets.cheatSheetContent extension point to your manifest. You can modify the details of the cheat sheet from here if necessary.
Features
You can help the user to load up your plug-in(s) as a single part, by combining them into one feature. Eclipse provides a wizard to create your feature through the New Project> Plug-in Development >Feature Project wizard.
This wizard generated a feature.xml file which has an editor, similar to the plug-in manifest editor, where you can change the details of your feature.
The most important section is the Plug-ins tab, which lists the plug-ins required for your feature. The Included Features tab allows you to specify sub-features to include as part of your feature. On the Dependencies tab, you can get all the plugins or features that you are dependent on by clicking on the Compute button.
A simple feature.xml may look as follows:
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="my.feature"
label="Feature"
version="1.0.0.qualifier"
provider-name="James">
<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<requires>
<import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.core.runtime"/>
</requires>
<plugin
id="com.dzone.refcard.rcpapp"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>
Branding
The feature also provides a single location where you can define all the branding for your application. In the Overview tab, you can assign a Branding Plug-in to the feature.
The branding plug-in needs to contain the following artefacts:
| Item | Purpose |
| about.html | A HTML file that will be displayed in the Plug-in Details>More Info dialog |
| about.ini | This file contains most of the branding information for the feature described below |
| about.properties | Used for localisation of the strings from the about.ini file. The values are referenced using the %key notation |
about.ini
| Property | Purpose |
| aboutText | Multiline description containing name, version number and copyright information. Will appear in the About>Feature Details>About Features dialog. |
| featureImage | A 32x32 pixel icon representation of the feature to be used across the relevant About dialogs |
All of the icons and files referenced by the about.ini file should be placed in this plug-in also.
Product Branding
A product is an entire distribution of an RCP application, rather than a feature intended to be part of an existing distribution. As such, products have additional branding requirements. To specify these extra parameters, a contribution to the org. eclipse.core.runtime.products extension point is required.
The product must be assigned the application to run, the name of the product (for the title bar) and a description. Further properties are added as name/value pairs underneath the product.

An application can be provided by using the org. eclipse.core.runtime.applications extension point
| Property | Purpose |
| windowImages | The image used for this application, in windows and dialogs. This should be in the order of the 16x16 pixel image, followed by the 32x32 |
| aboutImage | Larger image to be placed in the About dialog |
| aboutText | Multiline description containing name, version number and copyright information. Will appear in the About>Feature Details>About Features dialog. |
You can also provide most of these details in the Branding tab of the generated .product file.
Splash Screen
The .product file that is generated while creating your product includes a Splash tab. Here you can specify the plug-in that contains the splash.bmp file for your Splash screen. Typically, this should reside in your branding plug-in. The splash screen can also be customized with templates, and can include a progress bar with messages.
Getting Started with Drupal 7
By Cindy McCourt
21,670 Downloads · Refcard 59 of 187 (see them all)
Download
FREE PDF
The Essential Getting Started with Drupal 7 Cheat Sheet
Getting Started with Drupal 7
What is Drupal?
Though Drupal could be described as an open-source content management system, in reality it is much more: a framework upon which web developers can build many types of online experiences, including database-driven websites, document repositories, interactive applications, and more.
A Drupal Page
The word page is often used inconsistently in the Drupal community, but for this guide, I'll use webpage to refer to that which is displayed via a URL path such as /about or /contact-us. By understanding how a webpage is created in Drupal by default, you will better understand the tutorials to follow.
Drupal pages are created by the theme (barring the use of page layout modules) and consist primarily of the following:
- A header displaying the logo, site name, site slogan, and more.
- A main menu that includes links to the section landing pages.
- Multiple regions where you can place blocks of content and other functionality.
- A region displaying pages that define the webpage URL.
Webpage Header
Starting at the top, the content in the header area is managed in multiple locations. Site name and slogan are entered in the Site information, the logo is uploaded in the theme settings, and if you want other features to show in this area, your theme can be customized to accommodate.
Drupal Menus
Drupal 7 comes with four menus:
- The Main Menu is typically used to display links to the main sections of your site.
- The Navigation Menu provides links to create content and might include other links generated by modules.
- The Management Menu is the black admin bar you will see across the top of your screen.
- The User Menu includes the My Account and Logout links.
You can create your own menu as well. All menus are available as blocks and can be displayed in page regions.
Page Regions
The quantity, placement, behavior, and style of webpage regions are defined by your theme. The diagrams on this page show sample theme regions. There are countless region configurations if you create your own theme.
Regions can hold one or more blocks. If a block is not present, the region will collapse and become undetectable to the user.
Types of Drupal Pages
For this guide, the word page refers to that which appears in the content region (see diagrams). Pages generate URL paths that, in turn, deliver the webpage. The most common page is the node. The node is your article, your blog post, your event page, and so on. Other types of pages include (but are not limited to) the following.
Default teaser pages. By default, Drupal's homepage displays a teaser list of nodes. It also has a term teaser page, which displays all nodes tagged with a specific taxonomy term.
Views pages. These pages help you query the database and display bits of information about your nodes or other data. Views pages don't come by default with Drupal, but they're usually added when developing a site.
Panel pages. By including bundles of page layout modules, Panel pages provide a means of creating custom pages and node page layouts.
Webform pages. Webforms are online forms used to collect data from users and export that data for use elsewhere. Examples include a survey, contact form, sign up form, and so on.
Module pages. Module pages vary based on the module. If a module displays content or a form, it will likely come with a URL path for you to use. For example, the search module produces a search results page.
Administrative pages. In order to configure Drupal, you need to use Drupal's administrative pages. If you develop a module, you might create an admin page to configure the module.
Types of Content Nodes
Nodes are created using content types. Content types are Drupal forms used to collect, relate, and display data in the content region of the webpage. Content types have at least five things in common: a title, body (most of the time), author, post date, and URL path. But you can add more. Two content types come enabled by default: Basic Page and Article. Four content types come preconfigured in module and are available to be enabled: Blog Entry, Forum Topic, Book Page, and Poll. You can also create your own content type.
| Content Type | Description | Unique Feature |
|---|---|---|
| Basic Page | Used when the type of content does not repeat such as About Us and Directions. | NA |
| Article | Used when type of content will be added on a regular basis. | Includes an image and a tags field. Promoted to the default teaser homepage. |
| Blog Entry | Alternative to Article. | Comes with multiple teaser pages and links to user's blog. |
| Book | Used relating nodes similar to a table of contents. | Unique book navigation on the node and a book navigation block. Outline feature that creates the relationship works on all content types. |
| Forum Topic | Used to post a discussion topic in a forum. | Comes with multiple forum list pages. Engages Drupal Taxonomy system to organize topics into forums. |
| Poll | Ask your visitors a single, multiple-choice question. | Choose the number of options for the question and length of availability. Comes with a list page and with most recent poll question displayed. |
Getting Started
Install Drupal
After you've planned your site, the next step is to install Drupal on a web server. For detailed documentation on Drupal installation, please visit http://drupal.org/documentation/install. These instructions focus on installing Drupal on an actual web server. If you aren't ready to commit to a hosted solution, you can learn Drupal via a Drupal site installed on your personal computer.
One way to set a site on your computer is to use Acquia's dev desktop. This package will convert your computer to a local web environment and set up your Drupal site in a matter of minutes. Go to https://www.acquia.com/ downloads and download and install the Dev Desktop just as you would any other software package.
Configure Site Information
1. Click on Configuration in the black admin menu at the top of your screen.
2. Click on Site Information and configure any of the following:
- Your site name
- Site slogan (make sure your theme supports slogans)
- Default email address for the site
- Number of nodes to display in the homepage teaser
- Set alternate pages for errors
Create Content
To create either a Basic Page or an Article in Drupal 7:
1. Click Add content in the grey shortcut menu at the top of your screen.
2. Click the type of content you want to create.
3. Complete the form.
4. Save.
Find Content
1. Click on Find Content in the grey shortcut menu.
2. Use the filters to find a specific type of content.
3. Update one or more nodes with the update options.
4. Use the operations to edit or delete a node.
Create a Content Type
In order to create your own content in Drupal 7:
1. Click on Structure in the black admin menu.
2. Click on Content Types.
3. Click on Add Content Type.
4. Complete the form. Note: review each option carefully. There are too many to convey here.
5. Save your content type or save and add fields.

The configuration options apply to the nodes that the content type will create. When creating the node, you can override many of these settings node-by-node if you have the Administer Content permission.
Add Fields to Content Types
You can add fields to all contents types, even those content types created using a module. The steps to add a field will vary, depending on the field you're adding.
Add New Field
You have two options: 1. Use a field whose type comes with Drupal, or 2. Use a field module downloaded from Drupal.org (see the Modules section of this card).
1. Assuming you aren't already in the Manage Fields interface, click on Structure and then Content Types.
2. Click Manage Fields for the content type to which the field will be added.
3. Locate the Add New Field option.
User-defined functions can be created by providing a name, zero or more arguments, and a return value (optional). For example:
4. Enter a label for your field, type of data, and form element.
Anonymous Functions
Before you save, you have the option to edit the field name.
5. Save.
6. Read the screen that follows and respond accordingly and click Save Field Settings to be sent to the field configuration interface.
7. Read the configuration options, respond accordingly and click Save Settings.
Reuse an Existing Field
Drupal comes with an image and term reference field (Tags) for the Article content type. If you want to add an image field to an existing content type or your custom content type, you can reuse the existing image field.
Should you reuse a field? Here some factors to consider.
- Will you want to change the field settings from one content type to another? Click edit next to a field and observe features in the Settings box and features in the Field setting box. You can change Settings from one content type to another and not affect how that field is used. If you change the Field setting options (for example, Number of values) that change will affect all content types that use that field.
- Will you want to manage access to the field differently between content types? For example, will anonymous users be able to see an image on Article but not on a Book page? Field visibility and permissions are part of the Field settings, are unique to the field, and are provided via the Field Permissions module.
Add a Vocabulary to a Content Type
What is Drupal's Taxonomy?
From a content perspective, Drupal's taxonomy system provides a way to assign descriptive tags to nodes, making it easier for your site's visitors to locate related content.
From a technical perspective, each Drupal site has one taxonomy made up of multiple vocabularies. Each vocabulary contains multiple terms (or tags). Terms can have parent-child relationships with other terms. One term cannot be assigned to two vocabularies.
Create a Vocabulary
1. Click on Structures and then on Taxonomy.
2. Click on Add Vocabulary.
3. Complete the form and save.
4. Add terms to the vocabulary. Note: You can add fields via Manage Fields on the add/edit vocabulary screen.
Add Vocabulary Field
In Drupal 7, a vocabulary is now a field, and field type is a term reference. Use the steps covered in the "Add Fields to Content Types" section to add a vocabulary.
Form element options work for both single- and multi-select options for three types of form elements.
Autocomplete term widget (tagging) is a free tagging option. This means you can add terms to your vocabulary as you create your content versus being required to use a pre-defined list of terms.
Alternative to Term Reference Field
Traditional select lists (via the List (text) field ) are still an option with Drupal, but the term reference field can be a viable alternative. List (text) field has the select list and check box/radio button options.
Which strategy is best for you? Consider the following scenario. You have a data table with multiple columns and you have enabled sorting on the columns. You click on the column header to sort the field that holds the vocabulary term. The table rows get reordered based on the alphanumeric values of the term in that field.
But … what if an alphabetical sort isn't what you need? What if you need to control the order in which table rows are displayed? The List (text) field will sort of the value you store in the database. If you allow a person to select 'Three months prior' from the select list, but assign the value 1 to the database (1|Three months prior), then rows with this value will appear first. A selection of 'Two months prior' set to 2 (2|Two months prior) would appear next. And so on.

Once you have used the List (text) field, you cannot edit the a value that has been stored in the database. If the value and label are the same, consider the term reference field.
Configure URL Aliases
When a node is created in Drupal, the path is /?=node/23 where 23 is the NID (node ID). When clean URLs are enabled on the site and available on your server, the default path for a node is /node/23. Neither option means much to the user or to search engines. Also, they are not very friendly when it comes to defining rules for when a block will appear on a webpage. Hence, we have URL aliases, turning /node/23 into something like /myfavorite- hobby.
Drupal comes with the Path module. This module allows you to manually add a URL alias each time you create a node.
The Pathauto module provides a way for you to create aliases via content path patterns. For instance, all article paths might look like this: article/titleof- node where the title is provided with the [node:title] token. The screen shot below provides some examples.
Manage Display of Fields
When you are creating a node, you fill in the fields that are part of the content type form. The order in which those fields appear in the add/edit form is controlled by the same place you add fields, Manage fields.
The order in which the fields appear when the node is viewed by the public is controlled using the content type's Manage Display feature.
You can perform the following tasks.
- Reorder the order of the fields. Click+hold+drag the + sign next to the field to reposition the field.
- Manage the label display: Above, Inline, or
- Choose a format for the data to be displayed. Not all fields have format options.
- Refine formatting. Some fields allow you to take formatting a little further. For example, you can choose the image style you want for your Image field. (see "Image Styles" later in this card).
Create a Menu
Sometimes you need a list of menu links to appear in a section of your site. For example, a menu called About might include a link to Partners, History, Methodology, and so on. The About menu would be a block that you can place in a region and set to show only on the pages in the About site section.
1. Click on Structure and then on Menus.
2. Click on Add Menu.
3. Provide a menu title (a name for your menu).
4. Save.
5. Add menu items (links to pages) to your new menu.
Add a Page to a Menu
Add an Item via Menu Admin
1. Click on Structure and then on Menus.
2. Click Add Link next to the menu of choice.
3. Complete the form. Note: the URL path needs to exist first in order to add it to the menu.
4. Save.
Add an Item via a Module
When you create a node, you can add that node to a menu via the menu tab. You can also add nodes to menus via the menu admin interface.
The Views module creates page displays and a way for you to assign that page to a menu without having to go to the Menu admin pages. The Panels module provides the same type of option.
Some modules will add a page to a menu for you. The Forum module adds the Forums link to the Navigation menu when you enable that module. You can move the link to another menu if you wish by editing the menu item.
Manage Text Formats
Drupal 7 comes with three text formats: Plain text, Filtered HTML, and Full HTML. All roles on the site have access to plain text. You can select which roles utilize the HTML format options.
When text and HTML markup is added to a field configured to allow HTML, Drupal collects that content and stores it. When the node is viewed, Drupal looks at the text format settings for the node and send only that which the text format allows. For example, the Filtered HTML format does not have the table tags as approved HTML tags. If a user creates a node and includes a table, it will not show. You have two options:
1. Add the table tags to the list of allowed HTML tags by configuring the Filtered HTML format.
2. Give your users permission to choose Full HTML. Be careful with this as it gives your user a lot of power.
To manage text formats, go to Configuration > Text formats.
Add an HTML Editor
By default, Drupal does not come with an HTML editor installed. You can add an HTML editor one of two ways:
1. Use the WYSIWYG module and add an editor library such as CKEditor, TinyMCE, or others. You can add as many as you like. Assign the editor to a text format.
2. Use a module dedicated to one particular editor such as the CKEditor module.
Buttons should match the tags permitted by the text format to which it is assigned.
Adding Images
There are many ways to put an image on a page in Drupal. Below are four options to get you started.
Image Field
The advantage of this approach is the ability to reuse the images you upload. For example, you can create a page listing your nodes and include a thumbnail of the image associated with the node. The original image would be used but styled to fit using an image style.
Image field. Upload an image via a field and display the image from the field.
Image field and Insert. Upload an image via a field, hide the image from showing from the field, use the Insert module and insert the image into the body of the node.
HTML Editor Image Editor
The advantage of this approach is usability. If you are not going to reuse the image, sometimes it's easier for users to click the image icon on an editor bar.
HTML Editor. Install an HTML editor and use the Image editor button to add a link to an image that will be embedded in the body. Images can be uploaded manually to the server or link to an image via a URL.
HTML Editor and IMCE. Install an HTML Editor and the IMCE module. IMCE adds a browse option allowing you to upload an image to the server via the Image editor button.
Create an Image Style
When a user uploads an image with the Image field, you can't always predict the size of the image. With an image style, you can manage the display of the image field such that all images have a specific width and/ or height.
1. Click on Configuration and then on Image Styles.
2. Click on Add Style.
3. Give the style a name. Hint: Names like icon, thumbnail or small don't convey much about the style. A name like scale_100w says this style will scale the image (versus resize) and it will keep the image from distorting because the height is allowed to be whatever it needs to be after the width is set to 100 pixels.
4. Add one or more effects to the style to match the style name.
5. Update the style.
This style is now available for use in Manage Display and other modules that use image styles such as Insert, Views, and Panels.
Modules
Find and Choose Modules
Modules are bundles of code that add new or modify existing functionality in Drupal. Contributed modules can be found at http://drupal.org/project/ modules. A couple things to know about modules:
Dependencies. Modules can be dependent on other modules. Therefore you might need to install multiple modules to get the functionality you want.
Status. Module project pages have status information to help you decide if the module is supported. There are too many indicators to discuss here.
Install a Module
The process of installing a module will depend on your server environment. Each module contains a readme.txt and/or install.txt file with instructions on how to install that particular module. The general steps are:
1. Download the module tar.gz or zip file.
2. Upload the file to /sites/all/modules. You might need to create the 'all' and 'modules' directory.
3. Unpack or unzip the file. Note: If you are using FTP, you might need to reverse steps 2 and 3.
Enable a Module
You can enable a core, contributed, and/or custom module such as Blog, Forum, or Poll with the following steps:
1. Click on Modules in the black admin menu bar.
2. Check the box for the module(s) you want.
3. Save the configuration.

Drupal will remind you if you didn't enable a dependent module. When it does, click Continue and Drupal will do the rest.
Configure a Module
Modules vary significantly, so it's impossible to convey one process for module configuration. To learn more about a particular module's configuration, consider the following:
- Review the readme.txt file that comes with the module.
- Check the module's project page on Drupal.org.
- Search for online tutorials for the module.
- Ask for support in the module's issue queue.
Themes
Find a Theme
You learned at the start of the reference card that the theme controls your page layout. Go to http://drupal.org/project/themes to locate a theme you want to use (assuming you aren't building your own theme).
Dependencies. There are standalone themes, base themes, and subthemes. Subthemes depend on base themes.
Status. Theme project pages have status information to help you decide if the theme is supported. There are too many indicators to discuss here.
Install a Theme
The process of installing a theme will depend on your server environment. Each theme contains a readme.txt and/or install.txt file with instructions on how to install that particular theme. The general steps are below.
1. Download the theme tar.gz or zip file.
2. Upload the file to /sites/all/themes. You might need to create the 'all' and 'modules' directory.
3. Unpack or unzip the file. Note: If you are using FTP, you might need to reverse steps 2 and 3.
Enable a Theme
You can enable a core, contributed, or custom theme such as Garland, Stark, Danland, and so on with the following steps.
1. Click on Appearance in the black admin menu bar.
2. Locate the theme you want under Disable Themes.
3. Click on Enable and set default. You can choose to enable a theme and not set it as default, thus giving you the option to configure a change in your current site without anyone knowing until you are ready.
Configure a Theme
Themes vary but there are some consistencies regarding configuration. Each theme will have the following.
- Toggle display options. These options allow you to enable and disable features such as the logo, menus, user pictures, search, and more.
- Logo image settings. Note: the image will need to be the right size before you upload.
- Shortcut icon settings. This is also known as the favicon.
- Some themes will have extensive configuration options available to you. Omega, Fusion, AdaptiveTheme, to name a few, are base themes that add significant configuration options in the admin interface.
Configure Blocks
Once you have your theme enabled, you are ready to start configuring the blocks for your web pages. There are three decisions you need to make when configuring blocks.
1. In which region will the block appear?
2. Where in that region will the block appear?
3. When should the block appear?
Choose a Region
There are two ways to choose a region for your block.
1. Click on Structure and then on Blocks.
2. Locate the block you want to position.
3. Either use the Region dropdown or click Configure.
4. If you click Configure, you will be given the option to set the block for all enabled themes at once.
5. If you use the Region dropdown, remember to save your changes.
Choose a Location in the Region
If you have multiple blocks in one region, in what order should they appear? Place the blocks with the following steps.
1. Click on Structure and then on Blocks.
2. Locate the block you want to position.
3. Click+hold+drag the + next to the block to place the block.
4. Save.
Designate When the Block Should Appear
There are three conditions to choose from: 1. Pages, 2. Content type, and 3. Roles.
Pages. When using the Pages option, the condition is based on a URL path. If you declare that all Article nodes will have a path that begins with article, you can set a block for each article node by setting the Pages visibility condition to the following.
1. Only on the listed pages.
2. articles/* Note: This means that all pages whose URL path begins with mysitename.com/articles will show this block.
Content types. If you have a block that should appear on nodes of a specific type, regardless of their path, this is the condition you need.
Roles. If you want to control who sees the block, select the role. If you don't make any selection, all will be assumed.
You can use one or more of the conditions at a time. For instance, if Pages is … and Content type is … and Roles is …, then show block.
Managing Roles and Permissions
Throughout this Refcard, I've discussed two roles: anonymous and authenticated. In Drupal 7, there is also a third: administrator.
- Anonymous refers to those not logged into your site.
- Authenticated refers to those logged into your site.
- Administrator can do anything on your site by default.
The first user on a Drupal site user/1 cannot be stripped of administrative rights; this user is all-powerful. Use this role with care.
Create a Role
1. Click on People, then Permissions, then Roles.
2. Type the name of the role and click Add Role.
Set Permissions for Roles
1. Click on the Permissions tab.
2. Check the permission setting for each role.
3. Save permissions.
Configure User Account Settings
You have several configuration options regarding user accounts.
1. Click on Configuration in the black admin menu and then click on Account settings.
2. Review and edit your options to meet your needs.
Included in the account settings admin page are the emails that the system sends out. You can customize these, but remember these apply to all communications versus those that might be associated with one particular event on your site.
Add a User
1. Click on People.
2. Click on Add User.
3. Complete the form. Note: if you want to collect more information from the user, you can add fields with the Manage Fields tab.
4. Save.
JavaServer Faces 2.0
By Cay Horstmann
36,104 Downloads · Refcard 58 of 187 (see them all)
Download
FREE PDF
The Essential JavaServer Faces 2.0 Cheat Sheet
JavaServer Faces 2.0
JSF Overview
JavaServer Faces (JSF) is the “official” component-based view technology in the Java EE web tier. JSF includes a set of predefined UI components, an event-driven programming model, and the ability to add third-party components. JSF is designed to be extensible, easy to use, and toolable. This refcard describes JSF 2.0.
Development Process
A developer specifies JSF components in JSF pages, combining JSF component tags with HTML and CSS for styling. Components are linked with managed beans—Java classes that contain presentation logic and connect to business logic and persistence backends.

In JSF 2.0, it is recommended that you use the facelets format for your pages:
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”
xmlns:f=”http://java.sun.com/jsf/core”
xmlns:h=”http://java.sun.com/jsf/html”
xmlns:ui=”http://java.sun.com/jsf/facelets”>
<h:head>...</h:head>
<h:body>
<h:form>
...
</h:form>
</h:body>
</html>
These common tasks give you a crash course into using JSF.
Text Field
![]()
page.xhtml
<h:inputText value=”#{bean1.luckyNumber}”>
WEB-INF/classes/com/corejsf/SampleBean.java
@ManagedBean(name=”bean1”)
@SessionScoped
public class SampleBean {
public int getLuckyNumber() { ... }
public void setLuckyNumber(int value) { ... }
...
}
Button
![]()
page.xhtml
<h:commandButton value=”press me” action=”#{bean1.login}”/>
WEB-INF/classes/com/corejsf/SampleBean.java
@ManagedBean(name=”bean1”)
@SessionScoped
public class SampleBean {
public String login() {
if (...) return “success”; else return “error”;
}
...
}
The outcomes success and error can be mapped to pages in faces-config.xml. if no mapping is specified, the page /success.xhtml or /error.xhtml is displayed.
Radio Buttons
![]()
page.xhtml
<h:selectOneRadio value=”#{form.condiment}>
<f:selectItems value=”#{form.items}”/>
</h:selectOneRadio>
WEB-INF/classes/com/corejsf/SampleBean.java
public class SampleBean {
private static Map<String, Object> items;
static {
items = new LinkedHashMap<String, Object>();
items.put(“Cheese”, 1); // label, value
items.put(“Pickle”, 2);
...
}
public Map<String, Object> getItems() { return items; }
public int getCondiment() { ... }
public void setCondiment(int value) { ... }
...
}

Validation and Conversion
Page-level validation and conversion:
<h:inputText value=”#{bean1.amount}” required=”true”>
<f:validateDoubleRange maximum=”1000”/>
</h:inputText>
<h:outputText value=”#{bean1.amount}”>
<f:convertNumber type=”currency”/>
</h:outputText>
The number is displayed with currency symbol and group separator: $1,000.00
Using the Bean Validation Framework (JSR 303) 2.0
public class SampleBean {
@Max(1000) private BigDecimal amount;
}
Error Messages
![]()
<h:outputText value=”Amount”/>
<h:inputText id=”amount” label=”Amount” value=”#{payment.amount}”/>
<h:message for=”amount”/>
Resources and Styles
page.xhtml
<h:outputStylesheet library=”css” name=”styles.css” target=”head”/>
...
<h:outputText value=”#{msgs.goodbye}!” styleClass=”greeting”>
faces-config.xml
<application>
<resource-bundle>
<base-name>com.corejsf.messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
WEB-INF/classes/com/corejsf/messages.properties
goodbye=Goodbye
WEB-INF/classes/com/corejsf/messages_de.properties
goodbye=Auf Wiedersehen
resources/css/styles.css
.greeting {
font-style: italic;
font-size: 1.5em;
color: #eee;
}
Table with links

<h:dataTable value=”#{bean1.entries}” var=”row” styleClass=”table”
rowClasses=”even,odd”>
lt;h:column>
<f:facet name=”header”>
<h:outputText value=”Name”/>
</f:facet>
<h:outputText value=”#{row.name}”/>
</h:column>
<h:column>
<h:commandLink value=”Delete” action=”#{bean1.deleteAction}”
immediate=”true”>
<f:setPropertyActionListener target=”#{bean1.idToDelete}”
value=”#{row.id}”/>
</h:commandLink>
</h:column>
</h:dataTable>
WEB-INF/classes/com/corejsf/SampleBean.java
public class SampleBean {
private int idToDelete;
public void setIdToDelete(int value) { idToDelete = value; }
public String deleteAction() {
// delete the entry whose id is idToDelete
return null;
}
public List<Entry> getEntries() { ... }
...
}
Ajax 2.0
<h:commandButton value=”Update”>
<f:ajax execute=”
</h:commandButton>
lifecycle

The jsf expression language
An EL expression is a sequence of literal strings and expressions of the form base[expr1][expr2]... As in JavaScript, you can write base.identifier instead of base[‘identifier’] or base[“identifier”]. The base is one of the names in the table below or a bean name.
| header | A Map of HTTP header parameters, containing only the first value for each name |
| headerValues | A Map of HTTP header parameters, yielding a String[] array of all values for a given name |
| param | A Map of HTTP request parameters, containing only the first value for each name |
| paramValues | A Map of HTTP request parameters, yielding a String[] array of all values for a given name |
| cookie | A Map of the cookie names and values of the current request |
| initParam | A Map of the initialization parameters of this web application |
|
requestScope, sessionScope, applicationScope, viewScope 2.0 |
A map of all attributes in the given scope |
| facesContext | The FacesContext instance of this request |
| view | The UIViewRoot instance of this request |
| component 2.0 | The current component |
| cc 2.0 | |
| resource 2.0 | Use resource[‘library:name’] to access a resource |
Value expression: a reference to a bean property or an entry in a map, list or array. Examples:
userBean.name calls getName or setName on the userBean object pizza.choices[var] calls pizza.getChoices().get(var) or pizza.getChoices().put(var, ...)
Method expression: a reference to a method and the object on
which it is to be invoked. Example:
userBean.login calls the login method on the userBean object
when it is invoked. 2.0: Method expressions can contain parameters: userBean.login(‘order page’)
In JSF, EL expressions are enclosed in #{...} to indicate deferred evaluation. The expression is stored as a string and evaluated when needed. In contrast, JSP uses immediate evaluation, indicated by ${...} delimiters.
2.0: EL expressions can contain JSTL functions
|
fn:contains(str, substr), fn:containsIgnoreCase(str, substr) fn:startsWith(str, substr) fn:endsWith(str, substr) fn:length(str) fn:indexOf(str) fn:join(strArray, separator) fn:split(str, separator) fn:substring(str, start, pastEnd) |
fn:substringAfter(str, separator) fn:substringBefore(str, separator) fn:replace(str, substr, replacement) fn:toLowerCase(str) fn:toUpperCase(str) fn:trim() fn:escapeXml() |
JSF Core Tags
| Tag | Description/Attributes |
| f:facet | Adds a facet to a component - name: the name of this facet |
| f:attribute | Adds an attribute to a component - name, value: the name and value of the attribute to set |
| f:param | Constructs a parameter child component - name: An optional name for this parameter component. - value:The value stored in this component. |
| f:actionListener f:valueChangeListener | Adds an action listener or value change listener to a component - type: The name of the listener class |
| f:propertyAction Listener 1.2 | Adds an action listener to a component that sets a bean property to a given value - target: The bean property to set when the action event occurs - value: The value to set it to |
| f:phaseListener 1.2 | Adds a phase listener to this page - type: The name of the listener class |
| f:event 2.0 | Adds a system event listener to a component - name: One of preRenderComponent, postAddToView, preValidate, postValidate - listenter: A method expression of the type void (ComponentSystemEvent) throws AbortProcessingException |
| f:converter | Adds an arbitrary converter to a component - convertedId: The ID of the converter |
| f:convertDateTime | Adds a datetime converter to a component - type: date (default), time, or both - dateStyle, timeStyle: default, short, medium, long or full - pattern: Formatting pattern, as defined in java.text. SimpleDateFormat - locale: Locale whose preferences are to be used for parsing and formatting - timeZone: Time zone to use for parsing and formatting (Default: UTC) |
| f:convertNumber | Adds a number converter to a component - type: number (default), currency , or percent - pattern: Formatting pattern, as defined in java.text. DecimalFormat - minIntegerDigits, maxIntegerDigits, minFractionDigits, maxFractionDigits: Minimum, maximum number of digits in the integer and fractional part - integerOnly: True if only the integer part is parsed (default: false) - groupingUsed: True if grouping separators are used (default: true) - locale: Locale whose preferences are to be used for parsing and formatting - currencyCode: ISO 4217 currency code to use when converting currency values - currencySymbol: Currency symbol to use when converting currency values |
| f:validator | Adds a validator to a component - validatorID: The ID of the validator |
| f:validateDoubleRange, f:validateLongRange, f:validateLength |
Validates a double or long value, or the length of a string - minimum, maximum: the minimum and maximum of the valid range |
| f:validateRequired 2.0 | Sets the required attribute of the enclosing component |
| f:validateBean 2.0 | Specify validation groups for the Bean Validation Framework (JSR 303) |
| f:loadBundle | Loads a resource bundle, stores properties as a Map - basename: the resource bundle name - value: The name of the variable that is bound to the bundle map |
| f:selectItem | Specifies an item for a select one or select many component - binding, id: Basic attributes - itemDescription: Description used by tools only - itemDisabled: false (default) to show the value - itemLabel: Text shown by the item - itemValue: Item’s value, which is passed to the server as a request parameter - value: Value expression that points to a SelectItem instance - escape: true (default) if special characters should be converted to HTML entities - noSelectionOption 2.0: true if this item is the “no selection option” |
| f:selectItems | Specifies items for a select one or select many component - value: Value expression that points to a SelectItem, an array or Collection, or a Map mapping labels to values. - var 2.0: Variable name used in value expressions when traversing an array or collection of non-SelectItem elements - itemLabel 2.0, itemValue 2.0, itemDescription 2.0, itemDisabled 2.0, itemLabelEscaped 2.0: Item label, value, description, disabled and escaped flags for each item in an array or collection of non-SelectItem elements. Use the variable name defined in var. - noSelectionOption 2.0: Value expression that yields the “no selection option” item or string that equals the value of the “no selection option” item |
| f:ajax 2.0 | Enables Ajax behavior - execute, render: Lists of component IDs for processing in the “execute” and “render” lifecycle phases - event: JavaScript event that triggers behavior. Default: click for buttons and links, change for input components - immediate: If true, generated events are broadcast during “Apply Request Values” phase instead of “Invoke Application” - listener: Method binding of type void (AjaxBehaviorEvent) - onevent, onerror: JavaScript handlers for events/errors |
| f:viewParam 2.0 | Defines a “view parameter” that can be initialized with a request parameter -name, value: the name of the parameter to set -binding, converter, id, required, value, validator, valueChangeListener: basic attributes |
| f:metadata 2.0 | Holds view parameters. May hold other metadata in the future |
JSF HTML Tags
| Tag | Description | |
| h:head 2.0,h:body 2.0, h:form |
HTML head, body, form | |
| h:outputStylesheet 2.0, h:outputScript 2.0 |
Produces a style sheet or script | |
| h:inputText | Single-line text input control. |
|
| h:inputTextArea | Multiline text input control. |
|
| h:inputSecret | Password input control. | |
| h:inputHidden | Hidden field | |
| h:outputLabel | Label for another component for accessibility |
|
| h:outputLink | HTML anchor. | |
| h:outputFormat | Like outputText, but formats compound messages |
|
| h:outputText | Single-line text output. | |
| h:commandButton, h:button 2.0 |
Button: submit, reset, or pushbutton. | |
| h:commandLink, h:link 2.0 | Link that acts like a pushbutton. |
|
| h:message | Displays the most recent message for a component |
|
| h:messages | Displays all messages | |
| h:grapicImage | Displays an image | |
| h:selectOneListbox | Single-select listbox | |
| h:selectOneMenu | Single-select menu | |
| h:selectOneRadio | Set of radio buttons | |
| h:selectBooleanCheckbox | Checkbox | |
| h:selectManyCheckbox | Set of checkboxes | |
| h:selectManyListbox | Multiselect listbox | |
| h:selectManyMenu | Multiselect menu | |
| h:panelGrid | HTML table | |
| h:panelGroup | Two or more components that are laid out as one |
|
| h:dataTable | A feature-rich table component |
|
| h:column | Column in a data table |
Basic Attributes
| id | Identifier for a component |
| binding | Reference to the component that can be used in a backing bean |
| rendered | A boolean; false suppresses rendering |
| value | A component’s value, typically a value binding |
| valueVhangeListener | A method expression of the type void (ValueChangeEvent) |
| converter, validator | Converter or validator class name |
| required | A boolean; if true, requires a value to be entered in the associated field |
Attributes for h:body and h:form
| Attribute | Description |
| binding, id, rendered | Basic attributes |
|
dir, lang, style, styleClass, target, title h:form only: accept, acceptcharset, enctype |
HTML 4.0 attributes (acceptcharset corresponds to HTML accept-charset, styleClass corresponds to HTML class) |
|
onclick, ondblclick, onkeydown, onkeypress, onkeyup, onmousedown, onmousemove, onmouseout, onmouseover h:body only: onload, onunload h:form only: onblur, onchange, onfocus, onreset, onsubmit |
DHTML events |
Attributes for h:inputText, h:inputSecret,
h:inputTextarea, and h:inputHidden
disabled, lang, maxlength,
readonly, size, style,
styleClasstabindex, title
ondblclick, onfocus,
onkeydown, onkeypress,
onkeyup, onmousedown,
onmousemove, onmouseout,
onmouseover, onselect
Attributes for h:outputText and h:outputFormat
| Attribute | Description |
| escape | If set to true, escapes <, >, and & characters. Default value is true |
| Basic attributes |
|
| style, title | HTML 4.0 |
Attributes for h:outputLabel
| Attribute | Description |
| for | The ID of the component to be labeled. |
| binding, converter, id, rendered, value | Basic attributes |
Attributes for h:graphicImage
longdesc, style, styleClass, title,
url, usemap, width
ondblclick, onfocus, onkeydown,
onkeypress, onkeyup, onmousedown,
onmousemove, onmouseout,
onmouseover, onmouseup
Attributes for h:commandButton and h:commandLink
link tags only: charset, coords, hreflang, rel, rev, shape, target
onfocus, onkeydown, onkeypress,
onkeyup, onmousedown, onmousemove,
onmouseout, onmouseover,
onmouseup
Attributes for h:outputLink
Attributes for: h:selectBooleanCheckbox,
h:selectManyCheckbox, h:selectOneRadio,
h:selectOneListbox, h:selectManyListbox,
h:selectOneMenu, h:selectManyMenu
unselectedClass 2.0
ondblclick, onfocus, onkeydown,
onkeypress, onkeyup, onmousedown,
onmousemove, onmouseout,
onmouseover, onmouseup, onselect
Attributes for h:message and h:messages
Attributes for h:panelGrid
| Attribute | Description |
| bgcolor | Background color for the table |
| border | Width of the table’s border |
| cellpadding | Padding around table cells |
| cellspacing | Spacing between table cells |
| columns | Number of columns in the table |
| frame | frame Specification for sides of the frame surrounding the table that are to be drawn; valid values: none, above, below, hsides, vsides, lhs, rhs, box, border |
| headerClass, footerClass | CSS class for the table header/footer |
| rowClasses, columnClasses | Comma-separated list of CSS classes for rows/columns |
| rules | Specification for lines drawn between cells; valid values: groups, rows, columns, all |
| summary | Summary of the table’s purpose and structure used for non-visual feedback such as speech |
| binding, id, rendered, value | Basic attributes |
| dir, lang, style, styleClass, title, width | HTML 4.0 |
|
onclick, ondblclick, onkeydown, onkeypress, onkeyup, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup |
DHTML events |
Attributes for h:panelGroup
| Attribute | Description |
| binding, id, rendered | Basic attributes |
| style, styleClass | HTML 4.0 |
Attributes for h:dataTable
| Attribute | Description |
| bgcolor | Background color for the table |
| border | Width of the table’s border |
| cellpadding | Padding around table cells |
| cellspacing | Spacing between table cells |
| first | index of the first row shown in the table |
| frame | Specification for sides of the frame surrounding the table should be drawn; valid values: none, above, below, hsides, vsides, lhs, rhs, box, border |
| headerClass, footerClass | CSS class for the table header/footer |
| rowClasses, columnClasses | comma-separated list of CSS classes for rows/columns |
| rules | Specification for lines drawn between cells; valid values: groups, rows, columns, all |
| summary | summary of the table’s purpose and structure used for non-visual feedback such as speech |
| var | The name of the variable created by the data table that represents the current item in the value |
| binding, id, rendered, value |
Basic attributes |
| dir, lang, style, styleClass, title, width | HTML 4.0 |
|
onclick, ondblclick, onkeydown, onkeypress, onkeyup, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup |
DHTML events |
Attributes for h:column
| Attribute | Description |
|
headerClass 1.2, footerClass 1.2 |
CSS class for the column’s header/footer |
| binding, id, rendered | Basic attributes |
| Attribute | Description |
| ui:define | Give a name to content for use in a template -name: the name of the content |
| ui:insert | If a name is given, insert named content if defined or use the child elements otherwise. If no name is given, insert the content of the tag invoking the template -name: the name of the content |
| ui:composition | Produces content from a template after processing child elements (typically ui:define tags) Everything outside the ui:composition tag is ignored -template: the template file, relative to the current page |
| ui:component | Like ui:composition, but makes a JSF component -binding, id: basic attributes |
| ui:decorate, ui:fragment | Like ui:composition, ui: |
| ui:include | Include plain XHTML, or a file with a ui:composition or ui:component tag -src: the file to include, relative to the current page |
| ui:param | Define a parameter to be used in an included file or template -name: parameter name -value: a value expression (can yield an arbitrary object) |
| ui:repeat |
Repeats the enclosed elements
|
| ui:debug | Shows debug info when CTRL+SHIFT+a key is pressed
|
| ui:remove | Do not include the contents (useful for comments or temporarily deactivating a part of a page) |
Getting Started with Spring-DM
By Craig Walls
20,825 Downloads · Refcard 57 of 187 (see them all)
Download
FREE PDF
The Essential Spring-DM Cheat Sheet
Getting Started with Spring-DM
about spring-dm
Spring is a framework that promotes development of looselycoupled/ highly-cohesive objects through dependency injection and interface-oriented design. OSGi is a framework specification that promotes development of loosely-coupled/ highly-cohesive application modules through services and interface-oriented design. Seems like a match made in heaven! Spring Dynamic Modules (Spring-DM) brings Spring and OSGi together to enable a declarative service model for OSGi that leverages Spring’s power of dependency injection. This reference card will be your resource for working with Spring- DM to wire together OSGi services and ultimately building modular applications.
You may be interested to know that Spring-DM is the basis for the SpringSource dm Server, a next-generation application server that embraces modularity through OSGi. What’s more, the upcoming OSGi R4.2 specification includes a component model known as the OSGi Blueprint Services that is heavily influenced by Spring-DM.
Introducing Spring-DM
The star player of Spring-DM is a bundle known as the Spring- DM extender. The Spring-DM extender watches for bundles to be installed and inspects them to see if they are Springenabled (that is, if they contain a Spring application context definition file). When it finds a Spring-enabled bundle, the extender will create a Spring application context for the bundle.

Spring-DM also provides a Spring configuration namespace that enables you to declare and publish Spring beans as OSGi services and to consume OSGi services as if they were just beans in a Spring application context. This declarative model effectively eliminates the need to work with the OSGi API directly.
Installing Spring-DM
One of the nice things about Spring-DM is that you do not need to include it in the classpath of your OSGi bundles or even reference it from those bundles. Installing Spring-DM involves two parts:
- Installing the Spring-DM and supporting bundles in your OSGi framework
- Adding the Spring-DM configuration namespace to your bundle’s Spring configuration XML files
You can download Spring-DM from
http://www.springframework.org/osgi. The distribution comes
complete with everything you need to work with Spring-
DM, including the Spring-DM extender bundle and all of its
dependency bundles.
Installing the Spring-DM extender bundles
There are several means by which you can install bundles into an OSGi framework, depending on the OSGi framework and any add-ons or tools you may be using. But the most basic way is to use the “install” command that is available in most OSGi framework shells. For example, to install the Spring- DM extender bundle and the supporting Spring-DM bundles (assuming that you’ve unzipped the Spring-DM distribution in / spring-dm-1.2.0):
osgi> install file:///spring-dm-1.2.0/dist/spring-osgi-core-
1.2.0.jar
osgi> install file:///spring-dm-1.2.0/dist/spring-osgi-extender-
1.2.0.jar
osgi> install file:///spring-dm-1.2.0/dist/spring-osgi-io-
1.2.0.jar
Spring-DM depends on the Spring framework, so you’ll also need to install several other Spring bundles:

osgi> install file:///spring-dm-1.2.0/lib/spring-aop-2.5.6.A.jar
osgi> install file:///spring-dm-1.2.0/lib/spring-context-
2.5.6.A.jar
osgi> install file:///spring-dm-1.2.0/lib/spring-core-2.5.6.A.jar
osgi> install file:///spring-dm-1.2.0/lib/spring-beans-2.5.6.A.jar
Finally, you’ll also need to install several other supporting bundles that Spring and Spring-DM depend on:
osgi> install file:///spring-dm-1.2.0/lib/com.springsource.net.
sf.cglib-2.1.3.jar
osgi> install file:///spring-dm-1.2.0/lib/com.springsource.org.
aopalliance-1.0.0.jar
osgi> install file:///spring-dm-1.2.0/lib/com.springsource.slf4j.
api-1.5.0.jar
osgi> install file:///spring-dm-1.2.0/lib/com.springsource.slf4j.
log4j-1.5.0.jar
osgi> install file:///spring-dm-1.2.0/lib/com.springsource.slf4j.
org.apache.commons.logging-1.5.0.jar
osgi> install file:///spring-dm-1.2.0/lib/log4j.osgi-1.2.15-
SNAPSHOT.jar

The Spring-DM configuration namespace
Schema URI:
http://www.springframework.org/schema/osgiSchema XSD:
http://www.springframework.org/schema/osgi/spring-osgi.xsdWhen it comes to declaring services and service consumers in Spring-DM, you’ll use Spring-DM’s core namespace. To do that, you’ll need to include the namespace in the XML file.
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:osgi=”http://www.springframework.org/schema/osgi”
xsi:schemaLocation=”http://www.springframework.org/
schema/beans
http://www.springframework.org/schema/beans/
spring-beans.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/
osgi/spring-osgi.xsd”>
...
</beans>
Spring’s “beans” namespace is the default namespace, but if you know that most or all of the elements in the Spring configuration file will be from the Spring-DM namespace, you can make it the default namespace:

Publishing Services
To demonstrate Spring-DM’s capabilities, we’re going to create a few OSGi services that translate English text into some other language. All of these services will implement the following Translator interface:
package com.habuma.translator;
public interface Translator
{
String translate(String text);
}
The first service we’ll work with is one that translates English into Pig Latin. It’s implementation looks something like this:
package com.habuma.translator.piglatin;
import com.habuma.translator.Translator;
public class PigLatinTranslator implements Translator {
private final String VOWELS = “AEIOUaeiou”;
public String translate(String text) {
// actual implementation left out for brevity
}
}
If we were working with basic OSGi (that is, without Spring- DM), we’d publish this service to the OSGi service registry using the OSGi API, perhaps in a bundle activator’s start() method:
public void start(BundleContext context) throws Exception {
context.registerService(Translator.class.getName(),
new PigLatinTranslator(), null);
}
Although the native OSGi approach will work fine, it requires us to work programmatically with the OSGi API. Instead, we’ll publish services declaratively using Spring-DM. The first step: Create a Spring context definition file that declares the PigLatinTranslator as a Spring bean:
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://www.springframework.org/
schema/beans
http://www.springframework.org/schema/beans/springbeans.
xsd”>
<bean id=”pigLatinTranslator”
class=”com.habuma.translator.piglatin.PigLatinTranslator” />
</beans>

For example, if you’d rather place your Spring configuration files in a directory called “spring-config” at the root of the bundle, add the following entry to your bundle’s manifest: Spring-Context: spring-config/*.xml
This Spring context file can be named anything, but it should be placed in the Pig Latin translator bundle’s META-INF/ spring directory. When the bundle is started in an OSGi framework, the Spring-DM extender will look for Spring context configuration files in that directory and use them to create a Spring application context for the bundle.
Publishing a simple OSGi service
By itself the Spring context we’ve created only creates a bean in the Spring application context. It’s not yet an OSGi service. To publish it as an OSGi service, we’ll create another Spring context definition file that uses the Spring-DM namespace:
<<?xml version=”1.0” encoding=”UTF-8”?>
<<beans:beans xmlns:beans=”http://www.springframework.org/schema/
beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns=”http://www.springframework.org/schema/osgi”
xsi:schemaLocation=”http://www.springframework.org/
schema/beans
http://www.springframework.org/schema/beans/
spring-beans.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/
osgi/spring-osgi.xsd”>
<<service ref=”pigLatinTranslator”
interface=”com.habuma.translator.Translator” />
<</beans:beans>

This new Spring context file uses Spring-DM’s
Publishing a service under multiple interfaces
Let’s suppose that the PigLatinTranslator class were
to implement another interface, perhaps one called
TextProcessor. And let’s say that we want to publish the service
under both the Translator interface and the TextProcessor
interface. In that case, you can use the
<service ref=”pigLatinTranslator”>
<interfaces>
<beans:value>com.habuma.translator.Translator</beans:value>
<beans:value>com.habuma.text.TextProcessor</beans:value>
</interfaces>
</service>
Auto-selecting service interfaces
Instead of explicitly specifying the interfaces for a service, you can also let Spring-DM figure out which interfaces to use by specifying the auto-export attribute:
<service ref=”pigLatinTranslator”
auto-export=”interfaces” />
By setting auto-export to “interfaces”, it tells Spring-DM to publish the service under all interfaces that the implementation class implements. You can also set auto-export to “all-classes” to publish the service under all interfaces and classes for the service or “class-hierarchy.”
Publishing a service with properties
It’s also possible to publish a service with properties to qualify that service. These properties can later be used to help refine the selection of services available to a consumer. For example, let’s say that we want to qualify Translator services by the language that they translate to:
<rvice ref=”pigLatinTranslator”
interface=”com.habuma.translator.Translator”>
<service-properties>
<beans:entry key=”translator.language” value=”Pig Latin” />
</service-properties>
</service>
The <service-properties> element can contain one or more <entry> elements from the “beans” namespace. In this case, we’ve added a property named “translator.language” with a value of “Pig Latin”. Later, we’ll use this property to help select this particular service from among a selection of services that all implement Translator.
Consuming Services
Now that we’ve seen how to publish a service in the OSGi service registry, let’s look at how we can use Spring-DM to consume that service. To get started, we’ll create a simple client class:
package com.habuma.translator.client;
import java.util.List;
import com.habuma.translator.Translator;
public class TranslatorClient {
private static String TEXT = “Be very very quiet. I’m hunting
rabbits!”;
public void go() {
System.out.println(“ TRANSLATED: “ +
translator.translate(TEXT));
}
private Translator translator;
public void setTranslator(Translator translator) {
this.translator = translator;
}
}
TranslatorClient is a simple POJO that is injected with a Translator and uses that Translator in its go() method to translate some text. We’ll declare it as a Spring bean like this:
<?xml version=”1.0” encoding=”UTF-8”?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://www.springframework.org/
schema/beans
http://www.springframework.org/schema/beans/springbeans.
xsd”>
<bean class=”com.habuma.translator.client.TranslatorClient”
init-method=”go”>
<property name=”translator” ref=”translator” />
</bean>
</beans>
As with the service’s Spring context declaration, the name of this Spring context definition can be named anything, but it should be placed in the client bundle’s META-INF/spring folder so that the Spring-DM extender will find it.
The bean is declared with the init-method attribute set to call the go() method when the bean is created. And we use the <property> element to inject the bean’s translator property with a reference to a bean whose ID is “translator”.
The big question here is: Where does the “translator” bean come from?
Simple service consumption
Spring-DM’s <reference> element mirrors the <service> element. Rather than publishing a service, however, <reference> retrieves a service from the OSGi service registry. The simplest way to consume a Translator service is as follows:
<reference id=”translator”
interface=”com.habuma.translator.Translator” />
When the Spring-DM extender creates a Spring context for the client bundle, it will create a bean with an ID of “translator” that is a proxy to the service it finds in the service registry. With that id attribute and interface, it is quite suitable for wiring into the client bean’s translator property.
Setting a service timeout
In a dynamic environment like OSGi, services can come and go. When the client bundle starts up, there may not be a Translator service available for consumption. If it’s not available, then Spring-DM will wait up to 5 minutes for the service to become available before giving up and throwing an exception.
But it’s possible to override the default timeout using the <reference> element’s timeout attribute. For example, to set the timeout to 1 minute instead of 5 minutes:
<reference id=”translator”
interface=”com.habuma.translator.Translator”
timeout=”60000” />
Notice that the timeout attribute is specified in milliseconds, so 60000 indicates 60 seconds or 1 minute.
Optional service references
Another way to deal with the dynamic nature of OSGi services is to specify that a service reference is optional. By default, the cardinality of a reference to a service is “1..1”, meaning that the service must be found within the timeout period or else an exception will be thrown. But you can specify an optional reference by setting the cardinality to “0..1”:
<reference id=”translator”
interface=”com.habuma.translator.Translator”
cardinality=”0..1” />
Filtering services
Imagine that we have two or more Translator services published in the OSGi service registry. Let’s say that in addition to the Pig Latin translator there’s also another Translator service that translates text into Elmer Fudd speak. How can we ensure that our client gets the Pig Latin service when another implementations may be available?
Earlier, we saw how to set a property on a service when it’s published. Now we’ll use that property to filter the selection of services found on the consumer side:
<reference id=”translator”
interface=”com.habuma.translator.Translator”
filter=”(translator.language=Pig Latin)” />
The filter attribute lets us specify properties that will help refine the selection of matching services. In this case, we’re only interested in a service that has its “translator.language” property set to “Pig Latin”.
Consuming multiple services
But why choose? What if we wanted to consume all matching services? Instead of pin-pointing a specific service, we can use Spring-DM’s <list> element to consume a collection of matching services:
<list id=”translators”
interface=”com.habuma.translator.Translator” />
The Spring-DM extender will create a list of matching services that can be injected into a client bean collection property such as this one:
private List<Translator> translators;
public void setTranslators(List<Translator> translators) {
this.translators = translators;
}
Optionally, you can use Spring-DM’s <set> element to create a set of matching services:
<set id=”translators”
interface=”com.habuma.translator.Translator” />
The <list> and <set> elements share many of the same attributes with <reference>. For example, to consume a set of all Translator services filtered by a specific property:
<set id=”translators”
interface=”com.habuma.translator.Translator”
filter=”(translator.language=Elmer Fudd)” />
Testing Bundles
Hopefully, you’re in the habit of writing unit tests for your code. If so, that practice should extend to the code that is contained within your OSGi bundles. Because Spring-DM encourages POJO-based OSGi development, you can continue to write unit-tests for the classes that define and consume OSGi services just like you would for any other non-OSGi code.
But it’s also important to write tests that exercise your OSGi services as they’ll be used when deployed in an OSGi container. To accommodate in-OSGi integration testing of bundles, Spring-DM provides AbstractConfigurableBundleCreatorTests, a JUnit 3 base test class from which you can write your bundle tests.
What’s fascinating is how tests based on AbstractConfigurableBundleCreatorTests work. When the test is run, it starts up an OSGi framework implementation (Equinox by default) and installs one or more bundles into the framework. Finally, it wraps itself in an on-the-fly bundle and installs itself into the OSGi framework so that it can test bundles as an insider.
Writing a basic OSGi test
To illustrate, let’s write a simple test that loads our Translator interface bundle and the Pig Latin implementation bundle:
package com.habuma.translator.test;
import org.osgi.framework.ServiceReference;
import org.springframework.osgi.test.
AbstractConfigurableBundleCreatorTests;
import com.habuma.translator.Translator;
public class PigLatinTranslatorBundleTest
extends AbstractConfigurableBundleCreatorTests {
@Override
protected String[] getTestBundlesNames() {
return new String[] {
“com.habuma.translator, interface, 1.0.0”,
“com.habuma.translator, pig-latin, 1.0.0”
};
}
public void testOsgiPlatformStarts() {
assertNotNull(bundleContext);
}
}
The getTestBundleNames() method returns an array of Strings where each entry represents a bundle that should be installed into the OSGi framework for the test. The format of each entry is a comma-separated set of values that identify the bundle by its Maven group ID, artifact ID, and version number.
So far, our test has a single test method, testOsgiPlatformStarts(). All this method does is test that the OSGi framework has started by asserting that bundleContext (inherited from AbstractConfigurableBundleCreatorTests) is not null.
Testing OSGi service references
A more interesting test we could write is one that uses the bundle context to lookup a reference to the Translator service and assert that it meets our expectations:
public void testServiceReferenceExists() {
ServiceReference serviceReference =
bundleContext.getServiceReference(Translator.class.
getName());
assertNotNull(serviceReference);
assertEquals(“Pig Latin”,
serviceReference.getProperty(“translator.language”));
}
Here we retrieve a ServiceReference from the bundle context and assert that it isn’t null. This means that some implementation of the Translator service has been published in the OSGi service registry. Then, it examines the properties of the service reference and asserts that the “translator.language” property has been set to “Pig Latin”, as we’d expect from how we published the service earlier.
Testing OSGi services
One more thing we could test is that the Translator service does what we’d expect it to do. Certainly, this kind of test usually belongs in a unit test. But it’s still good to throw a smoke test its way to make sure that we’re getting the service we’re expecting.
We could use the ServiceReference to lookup the service. But, we can avoid any additional work with the OSGi API by having the Translator service wired directly into our test class. First, let’s add a Translator property and setter method to our test class
private Translator translator;
public void setTranslator(Translator translator) {
this.translator = translator;
}
When the test is run, Spring will attempt to autowire the property with a bean from its own Spring application context. But we haven’t defined a Spring application context for the test yet. Let’s do that now:
<?xml version=”1.0” encoding=”UTF-8”?>
<beans:beans xmlns:beans=”http://www.springframework.org/schema/
beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns=”http://www.springframework.org/schema/osgi”
xsi:schemaLocation=”http://www.springframework.org/schema/
beans
http://www.springframework.org/schema/beans/spring-beans.
xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd”>
<reference id=”translator”
interface=”com.habuma.translator.Translator” />
</beans:beans>
You’ll recognize that this Spring context definition looks a lot like the one we created for the service consumer. In fact, our test class will ultimately be a consumer of the Translator service. We just have one more thing to do before we can test the service—we’ll need to override the getConfigLocations() method to tell the test where it can find the context definition file:
@Override
protected String[] getConfigLocations() {
return new String[] { “bundle-test-context.xml” };
}
Now we can write our test method:
public void testTranslatorService() {
assertNotNull(translator);
assertEquals(“id-DAY is-thAY ork-wAY”,
translator.translate(“Did this work”));
}
This method assumes that by the time it is invoked, the translator property has been set. It first asserts that it is not null and then throws a simple test String at it to test that the service does what we expect.
Changing the tested OSGi framework
By default, Spring-DM tests are run within Equinox. But you can change them to run within another OSGi framework implementation such as Apache Felix or Knopflerfish by overriding the getConfigLocations() method. For example, to run the test within Apache Felix:
@Override
protected String getPlatformName() {
return Platforms.FELIX;
}
Or for Knoplerfish:
@Override
protected String getPlatformName() {
return Platforms.KNOPFLERFISH;
}
Providing a Custom Manifest
When a Spring-DM test gets wrapped up in an on-the-fly bundle, a manifest will be automatically generated for it. But if you’d like to provide a custom manifest. To provide a custom manifest for the on-the-fly bundle, all you need to do is override the getManifestLocation(). For example:
protected String getManifestLocation() {
return “classpath:com.habuma.translator.Translator.MF”;
}
Be aware, however, that if you provide a custom manifest, you must include a few things in that manifest to make Spring-DM testing work. First, you’ll need to specify a bundle activator:
Bundle-Activator: org.springframework.osgi.test.JUnitTestActivator
And you’ll need to import JUnit and Spring-DM packages:
Import-Package: junit.framework,
org.osgi.framework,
org.apache.commons.logging,
org.springframework.util,
org.springframework.osgi.service,
org.springframework.osgi.util,
org.springframework.osgi.test,
org.springframework.context
References
Example Source Code:
http://www.habuma.com/refcard/spring-dm/translator.zip
Spring-DM Homepage:
http://www.springframework.org/osgi
OSGi Alliance:
Modular Java on Twitter:
http://twitter.com/modularjava












































































