cheatsheet
Getting Started with Lean Software Development
By Curt Hibbs , Steve Jewett and Mike Sullivan
16,799 Downloads · Refcard 93 of 151 (see them all)
Download
FREE PDF
The Essential Lean Development Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with Lean Software Development
By Curt Hibbs, Steve Jewett, and Mike Sullivan
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.
About The Authors

Curt Hibbs
Curt Hibbs co-leads the Boeing team responsible for the adoption of Lean and Agile software engineering practices across Boeing's Defense, Space & Security business unit. He has been a software engineer for 30+ years, and during that time he has done just about everything related to developing software products, from working for WordStar, Hewlett Packard, the C.I.A, and more, to being the CTO of several startups. He has worked for Boeing since 2003.

Steve Jewett
Steve Jewett is a software developer with the Boeing Company, where he is involved in the development of cognitive decision support systems. Over a 25 year career he has developed software for automated test equipment, weapon/aircraft integration, embedded systems and desktop and web applications. He currently leads an agile software development team and works to promote Lean-Agile software development at Boeing.

Mike Sullivan
Mike Sullivan has over 6 years of experience teaching at the university level, and has spent the last 5+ years working with software teams in small companies and large corporations to drive valuable solutions and improve team dynamics. He is currently working in a small research team within a large corporation, implementing Lean techniques to improve the software his team delivers.
Recommended Book
This succinct book explains how you can apply the practices of Lean software development to dramatically increase productivity and quality. The Art of Lean Software Development is ideal for busy people who want to improve the development process but can't afford the disruption of a sudden and complete transformation. The Lean approach has been yielding dramatic results for decades, and with this book, you can make incremental changes that will produce immediate benefits.
BUY NOW

Curt Hibbs co-leads the Boeing team responsible for the adoption of Lean and Agile software engineering practices across Boeing’s Defense, Space & Security business unit.
Steve Jewett is a software developer with the Boeing Company, where he is involved in the development of cognitive decision support systems.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Eclipse Plug-in Development
By James Sugrue
14,183 Downloads · Refcard 70 of 151 (see them all)
Download
FREE PDF
The Essential Eclipse Plug-in Cheat Sheet
People who downloaded this DZone Refcard also liked:
Eclipse Plug-in Development
By James Sugrue
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.
About The Author

James Sugrue
James Sugrue is a software architect at Pilz Ireland, a company using many Eclipse technologies. James is also editor at both EclipseZone and Javalobby. Currently he is working on TweetHub, a Twitter client based on RCP and ECF. James has also written previous Refcardz covering EMF and Eclipse RCP.
Zone Leader: EclipseZone, Javalobby
Twitter: @dzonejames
Recommended Books
This book presents detailed, practical coverage of every aspect of plug-in development--with specific solutions for the challenges you’re most likely to encounter.
In Eclipse Rich Client Platform, two leaders of the Eclipse RCP project show exactly how to leverage Eclipse for rapid, efficient,cross-platform desktop development.
James Sugrue is the author of numerous Refcardz and the Zone Leader of Javalobby. Hes a software architect at Pilz Ireland, a company using many Eclipse technologies.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with ASP.NET MVC 1.0
By Simone Chiaretta and Keyvan Nayyeri
13,176 Downloads · Refcard 69 of 151 (see them all)
Download
FREE PDF
The Essential ASP.NET MVC Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with ASP.NET MVC 1.0
By Simone Chiaretta and Keyvan Nayyeri
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>
<% } %>
About The Author

Simone Chiaretta
Simone Chiaretta is a software architect and developer who enjoys sharing his development experience and more than 10 years' worth of knowledge on Web development with ASP.NET and other Web technologies. He is currently working as a senior solution developer for Avanade, an international consulting company. He is an ASPInsider Microsoft MVP in ASP.NET, a core member of Subtext, a popular Open Source blogging platform, an active member of the Italian .NET User Group, co-founder of the Italian ALT.NET user group and a frequent speaker for community events throughout Italy.

Keyvan Nayyeri
Keyvan Nayyeri is a software architect and developer who has a bachelor of science degree in applied mathematics. He was born in Kermanshah, Kurdistan, in 1984. Keyvan's main focus is on Microsoft development technologies and their related technologies. Keyvan has a serious passion for community activities and open source software. He is also a team leader and developer of some prominent .NET Open Source projects, where he tries to learn many things through writing code for special purposes. Keyvan also has received a number of awards and recognition from Microsoft, its partners, and online communities. Some major highlights include Microsoft VSX Insider and Telligent Community Server MVP.
Recommended Book
If you have a background in .NET and ASP.NET and are seeking to learn ASP.NET MVC, then this is the book for you. Relying heavily on MVC concepts, ASP.NET MVC principles, and code to demonstrate the main content, this valuable resource walks you through the necessary components to solve real-world problems.
Simone Chiaretta is a software architect for Avanade who has over 10 years of experience with ASP.NET and other Web technologies.
Keyvan Nayyeri is a team leader and developer of some prominent .NET Open Source projects. He is a Microsoft VSX Insider and Microsoft MVP.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with Oracle Berkeley DB
By Masoud Kalali
8,496 Downloads · Refcard 68 of 151 (see them all)
Download
FREE PDF
The Essential Berkeley DB Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with Oracle Berkeley DB
By Masoud Kalali
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.

About The Author

Masoud Kalali
Masoud Kalali holds a software engineering degree and has been working on software development projects since 1998. He has experience with a variety of technologies (.Net, J2EE, CORBA, and COM+) on diverse platforms (Solaris, Linux, and Windows). His experience is in software architecture, design and server side development. Masoud has several articles in Java.net. He is one of founder members of NetBeans Dream Team. Masoud’s main area of research and interest includes Web Services and Service Oriented Architecture along with large scale and high throughput systems' development and deployment.
Blog: http://weblogs.java.net/blog/kalali/
Contact: Kalali@gmail.com
Recommended Book
The Berkeley DB Book is a practical guide to the intricacies of the Berkeley DB. This book covers in-depth the complex design issues that are mostly only touched on in terse footnotes within the dense Berkeley DB reference manual. It explains the technology at a higher level and also covers the internals, providing generous code and design examples.
Masoud Kalali is an engineer at Informatics Matters. He is a founding member of the NetBeans Dream Team and a GlassFish community spotlighted developer.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with Selenium
By Frank Cohen
16,804 Downloads · Refcard 67 of 151 (see them all)
Download
FREE PDF
The Essential Selenium Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with Selenium
By Frank Cohen
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
About The Author

Frank Cohen
Frank Cohen is, Founder of PushToTest, Author of FastSOA. Through his speaking, writing and consulting, Frank Cohen, is the expert that information technology professionals and enterprises go to when they need to understand and solve problems in complex interoperating information systems, especially Service Oriented Architecture (SOA), Ajax, and Web services. PushToTest is the open-source test automation solutions business, and maintainer of the popular TestMaker open-source project
Website: www.pushtotest.com
The Cohen Blog: www.pushtotest.com/docs/thecohenblog
Recommended Book
As a Java developer, you want a guide that shows you how to add Ajax functionality to your web applications with a minimum of effort. Well look no further than Pro Ajax and Java Frameworks. In this book, recognized Java experts and authors of the best-selling Apress title, Foundations of Ajax, will show you how.
Frank Cohen is the founder of PushToTest, the open-source test automation solutions business, and a maintainer of the TestMaker open-source project.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with ServiceMix 4.0
By
9,227 Downloads · Refcard of 151 (see them all)
Download
FREE PDF
The Essential Getting Started with ServiceMix 4.0 Cheat Sheet
People who downloaded this DZone Refcard also liked:
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with Eclipse RCP
By James Sugrue
15,445 Downloads · Refcard 62 of 151 (see them all)
Download
FREE PDF
The Essential Eclipse RCP Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with Eclipse RCP
By James Sugrue
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.
About The Author

James Sugrue
James Sugrue is a software architect at Pilz Ireland, a company using many Eclipse technologies. James is also editor at both EclipseZone and JavaLobby. Currently he is working on TweetHub, a Twitter client based on RCP and ECF. James has also written a Refcard on EMF and has another Refcard on the way covering Eclipse Plug-ins.
Recommended Books
Building on two internationally bestselling previous editions, Eclipse Plug-ins, Third Edition, has been fully revised to reflect the powerful new capabilities of Eclipse 3.4.
In Eclipse Rich Client Platform, two leaders of the Eclipse RCP project show exactly how to leverage Eclipse for rapid, efficient, cross-platform desktop development.
James Sugrue is the author of numerous Refcardz and the Zone Leader of Javalobby. Hes a software architect at Pilz Ireland, a company using many Eclipse technologies.
your friends & followers...
DZone greatly appreciates your support.
Your download should begin immediately.
If it doesn't, click here.
Getting Started with Drupal
By Matt Vance
14,178 Downloads · Refcard 59 of 151 (see them all)
Download
FREE PDF
The Essential Drupal Cheat Sheet
People who downloaded this DZone Refcard also liked:
Getting Started with Drupal
By Matt Vance
about drupal
Drupal is an open source content management system and content management framework written in PHP. Drupal is used to power a variety of high-profile web sites, including sites for Popular Science (http://www.popsci.com/), Ubuntu (http://www.ubuntu.com/), and the Electronic Frontier Foundation (http://www.eff.org/).
Drupal is designed to be modular, with a number of optional modules included in the default “core” Drupal package. These modules serve to extend and enhance the capabilities of Drupal core. In addition, thousands of contributed modules are available for download from the central Drupal community website, Drupal.org.
Drupal is most often run on a LAMP server stack (an acronym for Linux, Apache, MySQL, and PHP). However, Drupal is not limited to a single architecture and can be run under Apple’s OS X or Microsoft Windows. Alternative web servers supported by Drupal include Microsoft IIS and lighttpd. In addition to MySQL, Drupal can also be run using PostgreSQL for database storage.

This Drupal Refcard will provide useful information to help you perform three of the common roles associated with setting up a new Drupal site: site building, theming, and development. This Refcard focuses on Drupal 6, the latest major release available as of this writing.
Drupal site building
Drupal can be used to create just about any type of website, from simple single-author blogs to multi-user social networking communities. Along with Drupal’s flexibility comes a steep learning curve. First time site builders can quickly become overwhelmed by the thousands of available contributed modules.
While the Drupal community strives to work together to create user friendly modules that combine together well, not all modules are created equal. Since developers can’t be expected to test their modules in combination with every other available module, there are bound to be incompatibilities. It is important, especially for first time site builders, to evaluate modules on a test site before installing them on a production site.
Not all Drupal modules are ready for prime time, but some modules have been around long enough and are useful for enough applications to warrant being on a site builder’s short list.

CCK
The Content Construction Kit module, also known as CCK (http://drupal.org/project/cck), allows site builders to extend beyond the default content types that are included with Drupal. Not only can the default page and story content types (sometimes called “node” types) be rearranged or customized with additional fields, but completely new content types can also be created. CCK includes several sub-modules for adding a variety of custom field types such as select boxes, check boxes, text boxes, and more. In addition, other contributed modules, such as Date (http://drupal.org/project/date), FileField (http://drupal.org/project/filefield), and ImageField

(http://drupal.org/project/imagefield), can be downloaded separately to add more complex fields to your custom content types.
Views
The Views module (http://drupal.org/project/views) allows site builders a great deal of control and flexibility in presenting lists of content, also called “views”, on a site. The Views module provides a graphical user interface that can output nodes, users, comments, and more. Views can be presented as pages, as RSS feeds, or “blocks” (the often small pieces of content that are typically reused on various pages in sidebars, headers, and footers). The individual items that make up a view can be customized in terms of sort order, fields displayed, and the format of the list (such as unordered lists or tables).

The Views module interface can take some time to master, but it is worth the investment. The flexibility of Views can be useful not just to site builders but also to developers, since views can be exported and bundled with modules.
Add on modules such as the Views Bonus Pack (http://drupal.org/project/view_bonus) can extend the Views module even more to present content as CSV files, Microsoft Word DOC files, or as XML.

Administration menu
The Administration Menu module (http://drupal.org/project/admin_menu) provides administrators with a small drop-down menu at the top of every page to allow easy access to the various administration pages that must be configured when building a new Drupal site.
Pathauto
The Pathauto module (http://drupal.org/project/pathauto) extends Drupal’s core Path module by automating the process of creating more user friendly and search engine friendly URL aliases for a site’s content. Pathauto requires and works in conjunction with the Token module (http://drupal.org/project/token).
Wysiwyg API
Drupal does not include a WYSIWIG editor by default; however, a wide variety of WYSIWYG and other client-side editors can be made to work with Drupal. The WYSIWYG API module (http://drupal.org/project/wysiwyg) provides Drupal integration for a variety of add-on editors, including: TinyMCE, FCKeditor, the YUI Rich Text Editor. Other modules provide support for individual editors, but it is likely that more will opt to integrate with the WYSIWYG API module going forward, in order to avoid duplicating development effort.

Drupal theming
Drupal provides a flexible theming layer to allow a site’s design to be highly customized. While Drupal can be used in conjunction with a variety of “theme engines” such as Smarty or PHPTAL, most users will want to become familiar with Drupal’s default theme engine format, PHPTemplate.
Depending on the needs of your site, you may choose to create a completely custom theme or use one of Drupal’s “starter themes” as the basis for a new site design. Starter themes such as Zen, Blueprint, or Framework strive to provide a basic foundation that can be customized to provide the look and feel your site requires.
To create your own custom theme from scratch, start by creating a new directory for the theme under the /sites/all/ themes directory. For example, to create a new theme called “Beautiful”, start by creating a new /sites/all/themes/beautiful directory.

.info file
Typically a theme directory contains a number of files that work together to make up the theme. At the very least, a [themename] .info file is required in order for Drupal to recognize a theme. Building on the example above, a minimal beautiful.info file might start with the following:
name = Beautiful
description = A example theme created for educational purposes.
core = 6.x
engine = phptemplate
A number of optional keys such as regions, stylesheets, and scripts can also be defined in order to override the defaults Drupal provides. More details can be found in the Drupal handbooks(http://drupal.org/node/171205).
Drupal themes typically contain a number of template files such as page.tpl.php or node.tpl.php. Each template file specifies how a particular portion of the site is to be presented. The various core modules provide default template files that can be copied into your theme directory and edited to customize them to suit the needs of a particular site.
Template files (.tpl.php)
The base template file found in most themes is the page.tpl. php file which acts as a wrapper around most of the other template files. When building a new theme, the default page. tpl.php theme file found in the /modules/system directory can provide a good starting point. You can copy that file into your theme’s directory and customize it as needed.

Additional template files can be used to customize the presentation of the various smaller elements of a Drupal site such as blocks, comments, polls, and more.
| Template file | Purpose |
| page.tpl.php | the main container template file, which acts as a wrapper for the other template files below; see the following page for a list of available variables within the page.tpl.php file: http://api.drupal.org/api/file/modules/system/page.tpl.php |
| page-front.tpl.php | can be used to specify a custom front page |
| node.tpl.php | controls how the various content types or “nodes” are displayed; see the following page for a list of available variables within the node.tpl.php file: http://api.drupal.org/api/file/modules/node/node.tpl.php/6 |
| node-[nodetype].tpl.php | optional template files used to target and customize nodes of a specific content type |
| block.tpl.php | contains the code used to display reuseable “block” content that may appear in multiple places within a site |
| block-[region].tpl.php | optional template files to customize how blocks in specific block “regions” will appear; regions are the areas specified in the theme’s .info file where blocks can be designated to appear (such as headers, sidebars, etc) |
| comment.tpl.php | controls the formatting of user comments |
Template files can be targeted to customize specific content of a site by naming the files according to specific “suggestions.” For example, to customize the front page of a site, create a copy of the page.tpl.php file named page-front.tpl.php and customize the new front page template as needed. See the Drupal handbooks (http://drupal.org/node/190815) for more details about the various core template files and how to use and customize the suggestion options.

template.php
The template.php file is an optional file used as a container
for conditional processing and overriding of theme functions.
In addition to overriding theme output using the template file
method outlined above, Drupal also allows theme functions
(any function beginning with “theme_”) to be overridden
inside the template.php file. Those more familiar with
programming in PHP may prefer to use template functions to
override Drupal’s defaults in order to gain more flexibility and
performance. A list of Drupal’s default theme functions can be
found on the Drupal API site
(http://drupal.org/api/group/themeable).

style.css
Drupal will automatically recognize a style.css file as a theme’s primary cascading style sheet file. Additional CSS files can be specified in the .info file using the “stylesheets” key.
screenshot.png
The screenshot.png file is a thumbnail sized image of the theme presented on Drupal’s theme administration page to provide users with a preview of how a theme will look.
Drupal development
Drupal has a reputation as being created by developers for developers. While it has made great strides recently at becoming more user friendly, Drupal still has a lot to offer developers. Drupal has been designed with flexibility in mind. Developers can customize the vast majority of Drupal’s functionality through Drupal’s system of hook functions.
Novice users should not be dissuaded from creating their own custom modules. Even a simple single-function module can be useful for things such as customizing how Drupal presents a particular piece of content or form.

To develop a new custom module, start by creating a new directory for the module under the /sites/all/modules directory. For example, to create a new module called “Functional”, start by creating a new /sites/all/modules/functional directory.

.info file
As with themes, each Drupal module must include at least a .info file in order to be recognized. An example functional.info file might consist of the following:
; $Id$
name = Functional module
description = “A simple example module created for educational
purposes.”
core = 6.x
See the Drupal handbooks (http://drupal.org/node/231036) for details on the other keys that can be specified in the module’s .info file.
Once the .info file has been created, a module can be enabled on the Module administration page (Site building > Modules). However, until the .module file has been created, the module won’t provide any new functionality.
.module file
The .module file typically contains the majority of the code for a module. Modules interact with the core of Drupal by implementing various hook functions that get called as Drupal carries out various tasks. Certain specific hook functions will need to be implemented depending on what functionality or customization a particular module needs to provide. A list of available hook functions can be found on the Drupal API Reference site (http://api.drupal.org/api/group/hooks).
For our example functional.module file, we will implement the hook_nodeapi function. By implementing hook_nodeapi, a module can act on the node object used as a container for the majority of content within Drupal.
To implement a particular hook function within a module, replace the word hook within the functions name with the name of the module. For example, in a module called functional, the hook_nodeapi function is implemented as functional_nodeapi:
<?php
function functional_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch ($op) {
case ‘view’:
$node->content[‘body’][‘#value’] .= “<br><br>Brought to you
by RefCardz”;
break;
}
}
Once the “functional” module is enabled, all nodes within the site will appear with a “Brought to you by RefCardz” notice at the bottom.

If you have the Devel module enabled, you can take advantage of more cleanly formatted output by using the following instead: dpm($variable);
By implementing hook_form_alter, modules can use Drupal’s Form API to add, remove, or change forms. For example, some sites use the Views module or Panels module to customize the site’s front page, so the “Promoted to front page” publishing option may need to be removed to avoid confusion. The following code will remove the checkbox used to promote content to the front page.
function functional_form_alter(&$form, $form_state, $form_id) {
if ($form_id == ‘page_node_form’) {
unset($form[‘options’][‘promote’]);
}
}
For a more detailed introduction to the Forms API, see the “Forms API Quickstart Guide” (http://api.drupal.org/api/file/ developer/topics/forums_api.html)
| Useful Hook Functions
(for a complete listing of hook functions, see http://api.drupal.org/api/group/hooks/) |
Description |
| hook_block http://api.drupal.org/api/function/hook_block/ |
Declare a block or set of blocks |
| hook_cron http://api.drupal.org/api/function/hook_cron/ |
Perform periodic actions |
| hook_db_rewrite_sql http://api.drupal.org/api/function/hook_db_rewrite_sql/ |
Rewrite database queries, usually for access control |
| hook_enable http://api.drupal.org/api/function/hook_enable/ |
Perform necessary actions after module is enabled |
| hook_form_alter http://api.drupal.org/api/function/hook_form_alter/ |
Perform alterations before a form is rendered |
| hook_mail_alter http://api.drupal.org/api/function/hook_mail_alter/ |
Alter any aspect of the emails sent by Drupal |
| hook_mail http://api.drupal.org/api/function/hook_mail/ |
Prepare an email message based on parameters |
| hook_menu http://api.drupal.org/api/function/hook_menu/ |
Define menu items and page callbacks |
| hook_perm http://api.drupal.org/api/function/hook_perm/ |
Define user permissions |
| hook_user http://api.drupal.org/api/function/hook_user/ |
Act on user account actions |
| hook_watchdog http://api.drupal.org/api/function/hook_watchdog/ |
Log an event message |
.install file
Another file commonly found in Drupal modules is the .install file. The .install file is used to store code that is run when a module is installed or uninstalled, such as the hook_schema and hook_install functions.
| Common .install File Functions | Description |
| hook_install http://api.drupal.org/api/function/hook_install/ |
Install the current version of the database schema, and any other setup tasks. |
| hook_schema http://api.drupal.org/api/function/hook_schema/ |
Define the current version of the atabase schema. |
| hook_uninstall http://api.drupal.org/api/function/hook_uninstall |
Remove any tables or variables that the module sets. |
Modules for developers
Modules for Developers
Several of the contributed modules for Drupal provide tools useful to module developers.
Deadwood
As new versions of Drupal get released, it can take a while for existing modules to get upgraded. The Deadwood module (http://drupal.org/project/deadwood) helps speed up the process of upgrading Drupal modules by automating some of the code updates.
Devel module
The Devel module (http://drupal.org/project/devel) provides tools for clearing Drupal’s cache, for generating dummy content, for debugging access issues, for performance logging, and much more.

The Devel module also includes an open source debugging tool called Krumo that can display a structured representation of any PHP variable. Devel adds “Dev load” and “Dev render” tabs to nodes which output the Node object through Krumo. With Devel enabled, you can output your own variables through Krumo using Devel’s print message function, dpm().
Coder module
Since the Deadwood module doesn’t completely automate the process of upgrading modules from one version of Drupal to the next, there is usually some manual coding to be performed after running Deadwood. That is where the Coder module (http://drupal.org/project/coder) comes in handy. The Coder module does not modify code, but it provides an automated code review that can pinpoint areas of code that need to be updated.

The Coder module can also help enforce coding standards by pinpointing sloppy coding and suggesting ways to clean it up. The Coder module can be especially helpful to run before contributing code back to the community at Drupal.org. Schema
The Schema module (http://drupal.org/project/schema)
provides tools for working with Drupal’s database Schema API. If you’ve already manually created the tables required by a module, the schema module can provide the corresponding schema data structure to be added to your module’s .install file, making it easier to replicate the same tables on another Drupal installation.
Cache Disable
Drupal’s caching system can be a source of confusion and productivity loss, if you are not careful. Rather than having to remember each of the various tasks that require the cache to be flushed, install and enable the Cache Disable module (http://drupal.org/project/cache_disable) when doing development on a new site. Just remember to turn the module off, once you have completed your development work.
API
The API module (http://drupal.org/project/api) is used to generate the hyperlinked documentation found at api.drupal. org. The same module can be used to provide a local version of Drupal’s API documentation. In addition to providing documentation on Drupal’s core modules, the API module can also generate documentation pages for installed modules that follow Drupal’s coding standards. If you prefer not to set up your own API site, you can still browse the documentation for many of the contributed modules, courtesy of Drupal consulting company Lullabot (http://api.lullabot.com/)
Other API Modules
Though Drupal does provide a full-fledged development framework, it doesn’t include everything one might need for every possible coding task. Thankfully, the repository of contibuted modules on drupal.org includes quite a few API modules. Many of the API modules provide no functionality on their own, but provide API code that other modules and module developers can build on. Example API modules include the Voting API (http://drupal.org/project/feedapi), Chart API (http://drupal.org/project/chart), and the Import/ Export API (http://drupal.org/project/importexportapi).
Resources
| URL | Reference |
| http://api.drupal.org/ | Documentation of Drupal’s API |
| http://drupal.org/handbooks | The Drupal community maintains several handbooks including documentation for beginners, themers, and developers |
| http://drupalcodesearch.com/ | Drupal Code Search allows users to search much of Drupal’s contributed code, though the index may not reflect the latest up-to-the-minute changes |
| http://cvs.drupal.org/ | A web interface to browse the code in the Drupal.org CVS repository, from the start of the project to the latest in contributed modules |
| http://drupalmodules.com/ | Drupal Modules allows users to rate modules. Ratings can be handy when choosing modules to use on a site |
| http://drupal.org/planet | Drupal Planet aggregates a number of blogs that post regularly about Drupal |
| http://groups.drupal.org/ | Groups.Drupal is a gathering place for niche groups within the Drupal community. Try searching for a user group near you or a group focused on your specific area of interest |
| http://drupal.org/irc | Learn how to connect to Drupals IRC channels and connect with a world-wide community of developers at all hours of the day |
| http://drupal.org/mailing-list | Drupal.org provides a number of mailing lists to keep the community up-to-date. Anyone running a public Drupal site should subscribe to the security announcements mailing list |
| http://association.drupal.org/ | The Drupal Association is a not-for-profit association charged with providing support to the Drupal project |
| http://drupal.org/getting-involved | The Drupal project thrives largely due to a strong community of contributors. Read the “Getting Involved” handbook to learn how you too can contribute |
| http://ww.lullabot.com/podcast | Several Drupal podcasts exist, both in audio and video formats, but the Lullabot podcasts are longest-running and arguably the most in-depth |
About The Author

Matt Vance
is a Web developer, technology consultant, and freelance writer living in Austin, Texas. He has written for Macworld magazine and Lifehacker.com. He can be contacted through his website, http://minezone.org/Recommended Book
Newcomers will find a thorough introduction to the framework, while experienced Drupal developers will learn best practices for building powerful websites. With Using Drupal, you’ll find concrete and creative solutions for developing the exact community website you have in mind.

