Best practices
Developers of Sonar core should :
- build with maven before commiting to subversion. Continuous integration watches you !
- commit frequently into subversion
- never commit incomplete changes (Subversion is not a backup system)
- use meaningful comments when doing a subversion commit, always with the JIRA key and title (e.g. "SONAR-6 Apply license LGPL")
- subscribe to both mailing-lists user@sonar.codehaus.org and scm@sonar.codehaus.org
- abuse of unit tests (JUnit 4), with the help of hamcrest matchers and mock objects (Mockito)
- test the web interface on MySql AND Derby
- think IoC (Inversion of Control pattern)
- abuse of functional tests (Selenium). Tests are written in the Selenese format (HTML).
- don't reinvent the wheel : use standard libraries like commons-lang, commons-collections and commons-io.
- use comments and javadocs only when necessary
- do not forget the license header on all Java and Ruby files
- respect the code formatting described below
Code formatting
- replace tabulations by 2 whitespaces
- classes with acronyms are CamelCase : for example prefer PmdPlugin to PMDPlugin, or JavaNcssHandler to JavaNCSSHandler
- follow this template :
- never do this :
- but this :
Tips and tricks
Connect to Derby from command line
- download derby(the same version as used by sonar)
- set the DERBY_HOME property
- execute the command $DERBY_HOME/bin/ij
- connect to the database :
Compare XML files from JUnit
Use XMLUnit. The dependency is already defined into maven.
Warning : There's a bug on the similar() method. Contrary to the documentation, it fails if nodes are not in the same order.
Override Object.equals(), hashCode() and toString()
You can use EqualsBuilder and HashCodeBuilder from commons-lang to simplify. Just define the fields to compare. Example on the Rule class :
Debug the Maven plugin from an IDE
- Two different ways :
1. Execute Maven debug command line : mvnDebug
2. Or edit $MAVEN_OPTS with :
Then execute Maven. It should block on :
- Attach your IDE to the remote process (the listening port is 8000).
Example on Intellij Idea : Run -> Edit configurations -> Add new configuration -> Remote -> port 8000.
Execute Selenium tests
- From firefox :
-
- install the SeleniumIDE 1.0b2 extension
- open the Selenium sidebar (View >> Sidebar >> SeleniumIDE)
- uncheck the option "Remember base URL" from Selenium IDE >> Options >> Options
- browse to Sonar (for example http://localhost:9000)
- open a selenese test from tests/integration/src/it/selenium/
- run it
- Or from maven :
- cd tests/integration
- mvn install -P[browser] # with [browser] = firefox or ie or safari
Use JUnit4 advanced features
- assertThat() over assertTrue() :
Stacktraces are more readable :instead of :
- use hamcrest extensions :
REST API
- Ressources url is : http://\[SERVEUR\]/api/\[RESSOURCE\]/\[ID\]/\[RESOURCE\]/...
Exemple : http://\[SERVEUR\]/api/projects/org.sonar.samples:main-sample/measures - Parameters are :
- written in lowercase
- don't contains "-", "_"
- the boolean use "true", "false"
- In Xml, lists are implied.
Exemple for project links: - In Json, all content is between "[]", and lists are between "[]"
Exemple :
GWT API
Dynamic gwt module loading
To allow the gwt module loading, we have define our own Linker, which implements XSLinker.
We overrride the getSelectionScriptTemplate() to use our own template.
We copy the the XSTemplate.js found in gwt-dev-
\com\google\gwt\core\linker dir, and modify it as follows :
- In computeScriptBase() function, we comment "$doc.write('<script id="' + markerId + '"></script>');" line because it seems that "$doc.write" stop the script execution.
- At the end of the _MODULE_FUNC_(), we comment all line begining with "$doc.write('<script><!--\n", for the same reason as above.
- Before the end of the _MODULE_FUNC_(), we add the following code :

