Java CoG Kit Coding Guide
From Java CoG Kit
Gregor von Laszewski and Mike Hategan
Version: 4.1.5 and up
This document includes basic information about coding conventions and how to add new modules to the Java CoG Kit.
Contents |
Coding Conventions
In case you like to contribute to the Java CoG Kit we have established these simple coding guidelines.
The Java CoG Kit follows the basic coding conventions given in the "Sun Coding Conventions for the Java Programming Language" HTML. Additionally we have the following rules given in this guide.
Versioning
Java CoG Kit Version Numbers
The version for the CoG Kit can be found in the cog/VERSION file. It follows the same rules as for module versions. Please, note that the Java CoG Kit verison number and the version mumbers for modules differ. Consider the Java CoG Kit as one big module.
the VERSION file should be renamed to VERSION.txt
the module versioning is not documented, so no one knows what these rules are.
Module Version Numbers
Java CoG Kit modules must include an acurate versioning. Every time your make a change in a module and commit it to SVN, it needs to be associated with a version that can be figured from just the jar file.
The version of the module is to be integrated in the file
VERSION.txt
many modules do not have a version number indicating that the documentation is not complete.
This version reflects a per module version number. In addition you must include an entry into into bf two CHANGES.txt file. One, that you maintain as part of your mpodule in which you can include a lot of details about changes, and one in the Chava CoG Kit main directoury in which you write a summary of the cahnges. Many times, you can just write the same changes in both files.
The version numbers you will use between versions are minor versions.
Modules must not have an “_” in their directory name. Instead all modules must use an “-” as this will simplify our process that we use to autogenerate documentation from the modules.
Directory names
Directory names must not have an “_” in their directory name. Instead all modules must use an “-” if realy necessary.
Java Conventions
Imports
All imports must be single class and explicit. That is, import <package>.* is not allowed.
Indentation
All indentation levels should be 2 spaces. No editor tabs are allowed unless they are converted to 4 spaces before saving the file.
Brackets
All brackets must follow the Java Coding guidelines. E.g.
for (index = 0; index < length; index++) {
... code ...
}
Having the bracket below the “for” should be avoided. The reason for this is that our automatic code checking tools have an easier time to analyze the code.
Variables
No acronyms or abbreviations should be used. For example, a = b + mVarLen should be avoided. Instead, use: totalLength = partLength + newLength.
Instance Variables
Use “this.” prefix when referencing instance variables, for example:
public MyClass (ServicePropertiesInterface properties) {
this.properties = properties;
}
public int foo () {
int localInt = 3;
return this.instanceInt + localInt;
}
One-Liners
Even single line statements should be inside brackets, for example:
if (isEmpty) {
return;
}
Logging
Log4J should be used exclusively. System.out.println and System.err.println is not allowed. Further, exceptions should be logged.
Testing
Each component or class should have a JUnit test The tests should be put in test/ directory under each package directory. A very short introduction is avilable here.
Internationalization
The framework should be internationalized. The samples may be internationalized. The Java I18n/L10n Toolkit may be used to verify whether code is international. However as we do not have funding to support internationalization in our ongoing efforts, we treat it at this time with low priority.
Library Reuse
Treat all code as a library, and as a reusable component. Calls to System.exit() are disallowed (except the main method)
Exceptions
Use chained exceptions. Java CoG Kit provides two simple generic exception classes for chaining multiple exceptions together. Look at ChainedException and ChainedIOException.
System.out
Only commandline tools may call system.out. However it is better to assume that even command line tools should be written first with an exception and another wrapper should call System.out dependent on the exception. This way the command can be reused within other programs without terminating the JVM based on an error (see Logging).
Logging
We use the following conventions for using the log4j calls.
- Fatal
- Something from which the application cannot recover. Application must be terminated.
- Error
- An exceptional state was encountered, and the application is very likely to not behave correctly. Continue at your own risk
- Warn
- An exceptional state was encountered, but the effects will not be on the functional side (say, an icon is missing).
- Info
- Overall flow
- Debug
- Detailed flow and data dumps
More information about how to use log4j can be found at
To use log4j you need to include the following import statement
import org.apache.log4j.Logger;
If you use loggers in your code, they must be be private, final, and static.
private final static Logger logger = Logger.getLogger(HTTPPost.class);
In the code you can use statements such as
logger.info("An example for a Information statement: I eneterd this method");
logger.fatal("An example for a fatal error related to a URL", urlException);
logger.error("An example for an error", ioException)
logger.debug("An example for a debug statement");
logger.wran("An example for a warning statement");
In case you use a string concatination or other relevant lines to prepare the log message you must use an if statement before printing the log message to increase performance.
if(logger.isDebugEnabled()) {
logger.debug("variable="+variable);
}
The properties of the logging facilities can also be customised during runtime while modifying the log4j.properties file. An example is listed below.
#############
#Root category
#############
log4j.rootCategory=WARN, STDOUT, ERROR-DIALOG,LOG-FILE
# uncomment this one to use the ERROR-DIALOG and change root to DEBUG level
# log4j.rootCategory=DEBUG, STDOUT, ERROR-DIALOG, LOG-FILE
#############
# ERROR-DIALOG is an error dialog for the desktop that allows errors to be emailed
#############
log4j.appender.ERROR-DIALOG=org.globus.cog.gridface.impl.util.ErrorDialogAppender
# override the value for ERROR-DIALOG to WARN
log4j.appender.ERROR-DIALOG.level=WARN
log4j.appender.ERROR-DIALOG.headerPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
log4j.appender.ERROR-DIALOG.layout=org.apache.log4j.HTMLLayout
#############
# STDOUT is set to be a ConsoleAppender using a PatternLayout
#############
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=%-5p [%c] %x - %m%n
#############
# LOG-FILE appends to a log file and can be read using chainsaw
# and the chainsaw-config.xml file
#############
log4j.appender.LOG-FILE=org.apache.log4j.RollingFileAppender
log4j.appender.LOG-FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOG-FILE.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
log4j.appender.LOG-FILE.MaxFileSize=20KB
log4j.appender.LOG-FILE.Append=true
log4j.appender.LOG-FILE.File=example.log
#############
# customize classes
#############
log4j.logger.org.globus.cog.gridfaces=INFO
The Java CoG Kit Module Concept
It is easy to extend the CoG Kit through contributed modules. A template module that you can copy and modify can be found in modules/template. There are a few requirements that have to be imposed in order to keep consistency which we outline next.
Versioning
TBD.
Module Directory Structure
The basic directory structure that MUST exists for each module is:
etc/MANIFEST.MF.head etc/MANIFEST.MF.tail lib/ src/
Build files
There are four files that are required by the build system. An example is given in the modules/template directory.
- build.xml - should not be modified unless absolutely necessary. If there is a feature that you would like added to the build system, please tell Mike
- dependencies.xml - project dependencies are stored here. Please modify it to suit your needs.
- launchers.xml - launchers that you want created in the build process. Use the example in modules/template to see how to use it
- project.properties - The module properties. The module name MUST be the same as the directory name of the module. The last line in this file contains the library dependencies for this module. If you don't add the jar files that your project requires there, it will not build. The format is a comma separated list of files. I suggest using <jar-name>.* (so that licenses and other things belonging to a jar will also be copied). Please read below about the libraries.
Build targets
There are a few commonly used build targets:
- dist
- builds a module, its dependencies and creates a distribution directory that contains everything required to use the module.
- dist.joint
- does pretty much what dist does, but all compiled classes from all modules are put into one big jar file.
- jar
- creates a jar file for the current module in the dist/lib directory. It requires the dist/lib directory to be present, all dependencies and libraries to be compiled and the jars copied to the dist/lib directory. You should normally not need to use this target. Use "dist" instead.
- clean
- removes the compiled classes (the "build" directory)
- distclean
- removed both the compiled classes and the dist directory. It does recursively clean the dependencies.
- deploy.webstart
- creates a webstart package for the module. You may need to edit cog/webstart.properties.
Libraries
Libraries can be found in two places:
- cog/lib
- cog/modules/<yourmodule>/lib
The build system will automatically choose the library from either of the two directories. If a library exists in both directories, priority will be given to the library in the cog/lib directory. This may cause your module not to build. Please talk to Gregor or Mike in this case. Also please note that the libraries in your module may at any time move to the cog/lib directory.
Source
The sources for your module. Not much to say here :)
This needs more text. the reader will be confused.
Modules and Log4j
Due to potential conflicts with log4j initialization files, if you use log4j in your module please note the following:
- There is a global log4j initialization file in cog/etc/log4j.properties.root. It defines the root category and a few appenders. It will be automatically included in builds.
- Each module can additionally define specific log4j logging clauses.
This can be done in modules/<module-name>/etc/log4j.properties.module. Please do not re-define the root category there.
Modules and Java Webstart
Creating webstart deployments is easy. You would need to define the webstart launchers in the launchers.xml file of your module. Please take a look at the launchers.xml in the template module.
In order to pass arguments to the application or applet, you can use the "application-params" (for applications) or "applet-params" (for applets) parameters. You would need to literally provide all the arguments as XML tags, while also escaping XML characters.
Examples:
- You need to pass "one" and "two" as arguments to a webstart application. The correct format is:
<property name="application-params" value="<argument>one</argument> <argument>two</argument>"/>
- You need to pass "key1=value1" to an applet:
<property name="applet-params" value="<param name="key1" value="value1"/>"/>
In order to deploy the webstart applications, you need to first modify the cog/webstart.properties file to match your particular configuration. After that, you can issue the "ant deploy.webstart" command, either in the main cog directory or inside a module. An HTML index page will be automatically that will point to the generated jnlp files.
You can also put some metadata in your module that can be used to generate nice pages with the webstart applications. The structure is as follows:
<module>/meta/ <module>/meta/description.txt <module>/meta/icon.png <module>/meta/screenshot.(png|jpg) <module>/meta/<launcher-name>/ <module>/meta/<launcher-name>/description.txt <module>/meta/<launcher-name>/icon.png <module>/meta/<launcher-name>/screenshot.(png|jpg)
Quality Control Tools
Newlines in files
With some editors you will find ^M characters at the end of the line. You can use in a module the command:
ant fixeol
which will remove ^M in a given module.
Using PMD
this section is a replication
We recommend that that developers and contributors use PMD (http://pmd.sourceforge.net) to check their code. Many of the complaints that PMD generates should be taken seriously. Still, there are instances when PMD rules do not apply for a good reason and create false positives.
To use pmd, you need to download it and add all its jar files to the ../tools/pmd-2.3/lib directory. Afterwards, just run 'ant pmd' in the module you want to check. It will generate both an on-screen report and an HTML report (pmd-report.html). For our core developers we have a makefile in the ./cog directory that will install pmd appropriately by calling "make install-qc".
PMD
We are using findbugs and PMD to verify the coding standard.
Tools for to check or manipulate the code quality are currently located in
/cogkit/src/cog/tools
These tools may move to cogkit/tools in a seperate CVS that only developers have access to. After the move to SVN this no longer works.
]
There is a special directory called
./cogkit/src/cog/qualitycontrol
in that contains various configuration files for findbugs and pmd.
In future we may include different configuration files for other tools such as deriving UML diagrams.
These files are
./cogkit/src/cog/qualitycontrol/pmd.xml ./cogkit/src/cog/qualitycontrol/findbugs.fb
The files contain our current defaults. The appropiate quality control programs an be installed as follows.
cd ./cogkit/src/cog make install-qc
This makefile should at one point become an ant file.
Now you can invoke the quality control programs.
Findbugs
Find bugs can be run by
cd ./cogkit/src/cog make findbugs
Findbugs in Cygwin. Findbugs will not work in Cygwin. In order to invoke it on a Windows machine, you should type in the command findbugs command in a Windows CMD.EXE window.
cd ./cogkit/src/cog
cd qualitycontrol; \
’../../tools/findbugs-0.8.6/bin/findbugs.bat’ \
-textui -low -html -project findbugs.fb > findbugs.html
Publishing the Results. On Windows findbugs should be called in the Windows CMD.exe program, it does not work under cygwin.
The results of findbugs may be posted on the release distribution page as an http://www.cogkit.org/release/4_1_3/findbugs.html[HTML] document. This can be done by calling
make publish
Please note that not all errors are relevant. We will improve the code quality gradually.
We recommend that that developers and contributors use PMD (http://pmd.sourceforge.net) to check their code. Many of the complaints that PMD generates should be taken seriously. Still, there are instances when PMD rules do not apply for a good reason and create false positives.
To use pmd, you need to download it and add all its jar files to the cog/tools/pmd-2.3/lib directory. Afterwards, just run ’ant pmd’ in the module you want to check. It will generate both an on-screen report and an html report (pmd-report.html). For our core developers we have a makefile in the ./cog directory that will install pmd appropiatly by calling “make install-qc”.
Automatic Cron scripts
write the cron scripts for pmd and findbug and install them on gong or wiggum as a nightly run at around 3:00am
document them here
Eclipse
After the move to SVN this section is outdated
it is possible to import from SVN directly into eclipse whcih should be docmented and is the prefered way.
We do not recommend to use the CVS feature form eclipse at this time. Instead we recommend the following procedure.
1. Create directory “cogkit” under your cygwin home.
> mkdir cogkit > cd cogkit
2. Checking out from CVS from the pserver:
> cvs -d :pserver:anonymous@cvs.cogkit.org:/cvs/cogkit login > cvs -d :pserver:anonymous@cvs.cogkit.org:/cvs/cogkit checkout src/cog
with a login acount (We assume you use bash). In your bashrc file set
alias ncvs=’cvs -d <youruserlogin>@cvs.cogkit.org/cvs/cogkit
In a new shell you can no say
ncvs checkout -P src/cog
3. Open Eclipse.
4. Switch workspace if a workspace from a previous project is opened. Create a new Project Workspace directory “CogKit”. It would be better to make the workspace location different from the “cogkit” directory where you checked out the code.
(see Figure 1)
5. Create a new “Java Project”. The screen below is shown when a new project is to be created.
(see Figure 2)
6. Enter a Project Name “Cog” and choose “Create Project at external location”. Browse to find the “cogkit” directory within cygwin where the cogkit was checked out from the cvs.
(see Figure 3)
7. Click on “Configure Defaults” in the above screen and choose Project as the source and output folder.
8. Do not press enter since it will save the project. Click on the “Next” button instead. This will take you to the project Properties screen shown below.
(see Figure 4)
Make sure you don’t have the source folders on your build path since this will lead to a different kind of display of the directories within the eclipse “Package Explorer”. They can be added later on when a build needs to be done.
9. To add modules to the build path: Right click on Project -> Properties -> Java Build Path. Here you could add folders to the build path.
10. Commit to CVS: Log on to cygwin and go to the appropriate directory to do the commits. If adding a new file use cvs add before committing to cvs. Similarly, for to delete files from cvs remove the file from local directory and use cvs remove before committing.
Appendix
Refactoring Tip
In case one likes to refactor and query replace a string in a directory, I recommend you use perl. The example
perl -i -pe 's/was/new/g' */*.java
replaces all ocurrences of "was" with "new". Be careful when you do this. This is nice if you like to change package names. However refactoring tools are provided by many Java editors.
