1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Java Coding Guidelines

Code Style and Format

Naming

Item Name
Package Use root stem uk.org.ogsadai. Do not use underscores and uppercase characters.
Class CapitalizedFirstLetter
Method smallFirstLetterWithSubsequentCapitalization
Constant (static final) FULLY_CAPITALIZED_WITH_UNDERSCORES
Member mFirstLetterWithSubsequentCapitalization
Parameter smallFirstLetterWithSubsequentCapitalization
Local Variable smallFirstLetterWithSubsequentCapitalization
Local Final Variable smallFirstLetterWithSubsequentCapitalization
Static Variable smallFirstLetterWithSubsequentCapitalization
Type smallFirstLetterWithSubsequentCapitalization
  • Only constants may have underscores _ in their names.

Use of Acronyms

  • Acronyms in class and method names and variables should be in upper case, e.g. mURL, parseWSDL(), SOAPHandler. This is Sun's convention, e.g. ComboBoxUI.
  • For local variables, all lower-case can be used if appropriate, e.g. variables called url and wsdl are acceptable but myurl and somewsdl are not.

Member Variables

  • All non-final member variables must be either protected or private, in which case access or change should be supported, if required, by standard getX and setX methods.
  • The use of the final keyword is encouraged where applicable.

Use of final

  • All method arguments must be marked as final.
  • Use of final elsewhere is at a developer's discretion.

Scoping

  • Default (package level) scoping in code should be avoided, as this can make readability harder.
  • All methods and variables should be specified as private, protected or public.
  • If default scoping is required (for example, to restrict method access to other classes within the same package only), it should be clearly commented so.

Imports

  • All imports must be single class and explicit.
  • Do not use multiple importation (e.g. import .*).
  • Do not use duplicate or unused imports.
  • Do not explicitly import java.lang classes.

Indentation

  • All indentation levels should be exactly 4 spaces.
  • Do not use TAB characters - use 4 space strings.
  • Source files should look correctly indented when viewed in a simple text editor.

Line Length

  • Line length should not exceed 80 columns.
  • Continuation lines should be indented to the column just beyond the previous open parenthesis, e.g.
    myResult = myObjectName.myQuiteLongMethodName(param1,
                                                  param2);
    
  • If no open parenthesis exists, or there is not enough room left after the open parenthesis to do the above then you may instead indent 4 characters from the beginning of the previous line, e.g.
    myResult = myLongObjectName.myQuiteLongMethodName(
        myLongParmeterName);
    

Brackets

  • Curly brackets { } are put on separate lines, e.g.
    for (index = 0; index < length; index++)
    {
    
    }
    
  • Do not use empty blocks unless they are commented, e.g.
    } 
    catch (Exception e) 
    {
        // Must put a comment here
    }
    
  • Do not use nested blocks, e.g.
    } 
    catch (Exception e)
    {
        {
    
        }
    }
    

Variables

  • Do not use abbreviations, e.g. a = b + mVarLen should be avoided and totalLength = partLength + mLength used instead.
  • Each variable declaration should appear on its own line.
  • Loop variables should be defined inside loop constructs. This allows the JVM to perform optimisations and de-allocate the variables more quickly. It is also more readable, e.g.
    for (int i = 0; i < n; i++)
    {
        Object someObject = getObject(i);
    }
    
    is preferable to
    Object someObject = null;
    for (int i = 0; i < n; i++)
    {
        someObject = getObject(i);
    }
    

Instance Variables

  • Do not usethis. as a prefix when referencing instance variables.
  • Use a form that does not require the use of this, for example, mMyVariable = myVariable;.

Statements

  • All single line statements should use brackets, e.g.
    if (isEmpty) 
    {
        return; 
    }
    
  • Do not use empty statements (e.g. lone semicolons).
  • Do not use assignments in sub-expressions (e.g. String s = Integer.toString(i = 2);).
  • switch statements should have a default clause, which should come last in the statement.
  • Every case containing code should contain a break, return, throw or continue statement.
  • Boolean expressions should be as simple as possible, e.g. the following are discouraged:
    if (b == true) 
    
    or
    if (b) 
    {
        return false; 
    }
    else 
    {
        return true;
    }
    
    This is equivalent to the, much nicer, return (! b);.
  • Do not reassign method parameters within the method.
  • Method parameters should be declared final for efficiency.
  • No unnecessary parentheses (e.g. if((a.equals(b)))).
  • Declare arrays as String[] args, not String args[].

Modifier ordering

The order of modifiers should conform to the the Java Language Specification. The correct order is:

  1. public
  2. protected
  3. private
  4. abstract
  5. static
  6. final
  7. transient
  8. volatile
  9. synchronized
  10. native
  11. strictfp

Comments and JavaDoc

  • All comments must be done in JavaDoc and follow the JavaDoc guidelines http://java.sun.com/j2se/javadoc/writingdoccomments.
  • All class comments must have a JavaDoc tag of form:
    @author ...FILL IN THE AUTHOR...
    
  • All packages must contain a JavaDoc-compliant package.html file.
  • All methods, classes and attributes must be commented.
  • No JavaDoc warnings or errors should be thrown by the JavaDoc compiler.
  • Methods that implement an interface method can just be commented with
    /**
     * {@inheritDoc}
     */
    
    if there is nothing in the implementation method that a user of the API needs to know.
  • Classes committed to SVN should not include commented-out code or TODOs without good reason.
  • Methods building/parsing XML should state the XML Schema or give an example of the format.
  • Class, method, attribute and argument names should be marked up using <code>...</code> (and not <tt>...</tt>).
  • Methods that accept java.util.Map, List, Set, etc should specify what types they expect the keys and values in these objects to be, e.g.
    * ... List<Activity>
    * ... Map<String, Request>
    
  • Methods or classes that parse, manipulate or construct XML documents should document the expected/produced XML or contain a reference to the associated XML Schema.
  • Methods or classes that perform mappings from one type of "thing" to another (e.g. from one database data-type to another) should explicitly list each of the mappings.
  • If code is incomplete or requires extension then comment these with the prefix TODO, e.g.:
    // TODO - extend this method.
    
  • JavaDoc for thread-safe classes should state that they are as such.
  • JavaDoc for interfaces that expect their implementations to be thread-safe should state this requirement.
  • Classes or methods that expect system properties to be set should state the name of the property they use.

Hash Codes

  • Whenever writing a equals() method for a class then a hashCode() method must also be written.
    • See the java.lang.Object Java API description for the full contract.
  • If wrapping another object then an arbitrary value can be added to avoid collisions in HashMaps, e.g.
    public int hashCode()
    {
        return 31 * 132 + mName.hashCode();
    }
    

Getting Class Names

  • someObject.getClass().getName() should be used and not someObject.getClass().toString().

String Concatenation

  • String addition is strongly discouraged, e.g.
    String bangles = debbie + michael + susanna + michael;
    
  • StringBuffer should be used instead, e.g.
    StringBuffer banglesBuffer;
    banglesBuffer.add(debbie);
    banglesBuffer.add(michael);
    banglesBuffer.add(susanna);
    banglesBuffer.add(vicki);
    String bangles = banglesbuffer.toString();
    

Logging

  • Do not use System.out or System.err in server-side classes.
    • The exceptions to this rule are test classes and classes executable from the command-line where the print statements form part of the command-line interface for a user.
  • Classes must use uk.org.ogsadai.exception.DAILogger for logging, not Log4J.
  • DAILogger declarations must be of form:
          private static final DAILogger LOG = DAILogger.getLogger(ClassName.class);
    
  • Only the DAILogger class can have a Log4J dependency.
  • Use of debug and info logging MUST be conditional if there is string concatenation or other work done to build the log message. Compare and contrast:
    LOG.debug("The Bangles are a band!");
    
    if (LOG.isInfoEnabled())
    {
        LOG.debug("The Bangles consist of "
            + "Debbie, " + "Vicki, " + "Susanna, " + " and " 
            + "Michael");
    }
    
  • Information within OGSA-DAI is logged at the following levels:
    • FATAL - service setup or resource access or some serious problem that affects operation of an OGSA-DAI service.
    • ERROR - an internal error of concern but which the client cannot do anything about.
    • WARN - a problem caused by a client (and details of which are returned to the client) or an intenal problem that we gulp as unimportant.
    • INFO - general status information of interest to a service deployer.
    • DEBUG - anything useful for debugging.
  • Only exceptions can be logged at FATAL, ERROR or WARN levels.
  • Only uk.org.ogsadai.common.logging.MessageIDs can be logged at INFO level.
  • Any string can be logged at DEBUG level.

Exceptions

  • All exceptions must sub-class uk.org.ogsadai.exception.DAIException or uk.org.ogsadai.exception.DAIUncheckedException or existing sub-classes of these, e.g.:
    public class PearShapedException extends DAIException 
    {
        /** Copyright statement. */
        private static final String COPYRIGHT_NOTICE =  
            "Copyright (c) The University of Edinburgh, 2007";
    
        /**
         * Constructor.
         * 
         * @param thing
         *     Thing that went wrong.
         * @param blame
         *     Thing to blame.
         */
        public PearShapedException(String thing, String blame) 
        {
            super(ErrorID.PEAR_SHAPED_ERROR, new Object[] {thing, blame});
        }
    }
    
  • Every exception must have an associated uk.org.ogsadai.exception.ErrorID value, e.g.
    /**
     * Raised when something turns pear-shaped.
     *
     * Parameter 1: Thing that went wrong.
     * Parameter 2: Thing to blame.
     */
    public static final ErrorID PEAR_SHAPED_ERROR =
        new ErrorID("uk.org.ogsadai.PEAR_SHAPED_ERROR");
    
  • Every uk.org.ogsadai.exception.ErrorID must have an error message in a message bundle, either the defaultogsadai_message.properties message bundle or a custom one. e.g.

uk.org.ogsadai.PEAR_SHAPED_ERROR={0} turned pear-shaped and I know \ that {1} was to blame.

  • An error message can have zero or more place-holders.
  • Place-holders in error messages must be numbered {0} , {1} , {2} , ... in sequential order.
  • Note the fact that the number of entries in the array to the call by PearShapedException's constructor to its super-class constructor is the same as the number of place-holders in the uk.org.ogsadai.PEAR_SHAPED_ERROR message.
  • All OGSA-DAI messages must be prefixed by uk.org.ogsadai.
  • Do not pass English language strings into a constructor - it undermines the whole point of internationalization and ErrorIDs.
  • Do not ever pass Exception.getMessage() into exception constructors.
  • Only abstract exception classes should allow ErrorIDs in their constructors.
  • If you need to pass an ErrorID to an exception constructor then you probably need to define a new exception with an abstract super-class.
  • When writing an exception that wraps another exception / takes another exception into its constructor:
    • Preserve the causal chain where appropriate using the initCause() method, e.g:
      public AnotherPearShapedException(String thing, Exception cause)
      {
          super(ErrorID.ANOTHER_PEAR_SHAPED_ERROR, 
                new Object[] {thing, cause.getMessage()});
                super.initCause(cause);
      }
      
    • Do not pass the child exception's getMessage() into the wrapping exception's message parameter list.
  • Methods in service classes that are the entry points for service operation calls should always ensure they wrap all calls to other OGSA-DAI components within try-catch blocks.
  • As a last-change fail-safe these should catch java.lang.Throwable so no undesired exceptions can slip back to the client as service faults.
  • For server-side components that can communicate to clients outwith the services themselves, e.g. servlets, these guidelines also apply.
  • Only log an exception when:
    • The exception is gulped without being handed-on or wrapped in another exception that is then thrown .
    • The exception is handed over for transit to client (e.g. service layer or response document constructor).
  • Exceptions should be logged at WARN, ERROR or FATAL levels only
  • Continue to use Java RuntimeExceptions (e.g. IllegalArgumentException) where possible
  • No internationalization is needed for runtime exceptions such as IllegalArgumentException - these are a programmers fault.
  • Do not use SQLException for illegal arguments or unsupported operations if working within implementations of java.sql.ResultSet.

Changing Class and Package Names

  • If you make changes to class or package names then you must do a search through the code base as a whole and the user doc and change any occurrences there also.
  • Changes to resource classes and activity classes also need to be reflected in configuration files in SVN and the test system.
  • The simple rule is if you change a class or package name do a careful search and replace though all Java, XML, HTML, TXT and properties files - a careful search because we have some classes which have the same local name but different package names.

Developing Activities

  • Activity classes should be named as follows:
    • Server-side activity implementation classes should be post-fixed by Activity, e.g. MyNewDataProcessorActivity.
    • Corresponding client toolkit activity classes should not be post-fixed by Activity, e.g. MyNewDataProcessor.
  • All activities should have a user doc page:
    • See release-scripts/ogsa-dai/doc/src/DocBook/Developer/ActivitiesAppendix.xml and release-scripts/ogsa-dai/doc/DocBook/Developer/Activities/* for the format and the information it needs to contain.
  • When you've added an activity you should:
    • Add it to release-scripts/ogsa-dai/server-configuration/server-config/activities.txt.
    • Add it to local-config/activities.txt.
    • Add it to the appropriate resource files in:
      • release-scripts/ogsa-dai/server-configuration/server-config/resourceTemplates/*
      • release-scripts/ogsa-dai/server-configuration/config-blanks/*
      • local-config/resources/*
      • local-config/resourceTemplates/*
  • When writing or modifying activities, any illegal values that are provided as inputs must not be handled as IllegalArgumentExceptions}.

Tests

  • Tests are implemented using JUnit.
  • Each class should have a JUnit test suite (set of test cases).
  • Do not print out XML fragments via System.out or System.err - ANT outputs test reports in XML and these are then converted to HTML for the test dashboard. Arbitrary XML fragments printed by test classes can break this process.
  • The test class should have the same package name as the class being tested with the postfix Test.java:
    • e.g. the class Bangles.java has an associated test class BanglesTest.java.
  • The tests should cover the black-box functionality of the component including error cases.
  • There should also be concise and simple JavaDoc comments completed for each test method in the test.
  • All test classes should include a main method:
    public static void main(String[] args)
    {
        junit.textui.TestRunner.run(BanglesTest.class);
    }
    
  • All testX() methods should throw java.lang.Exception.

Keep it Clean

  • If you see that code looks inefficient or could be cleaned up or that JavaDoc is missing or inaccurate then you should e-mail the author rather than silently fixing the problem

Eclipse Setting

if you are going to use eclipse to develop OGSA-DAI code then these are the warning setting we recommend you use with eclipse. To set these find the preferences window:

  • Window->Preferences

Most of the settings can be set in

  • Java->Compiler->Errors/Warnings

Some are are also to be found in

  • Java->Compiler->JavaDoc

Code Style

non-static access to static member Warning
indirect access to static member Ignore
unqualified access to instance field Ignore
undocumented empty block Warning
access to a non-accessible member.. Warning
method with a constructor name Warning
parameter assignment Warning
non-extrernalizes strings Ignore

Potential programming problems

Serializable class without... Ignore
assignment has no effect Warning
possible accidental boolean assign.. Warning
finally does not complete normally Warning
empty statement Warning
using a char array in string concat Warning
hidden catch block Warning
inexact type match Warning
boxing and unboxing Warning
enum type constant.. Warning
switch case fall through Warning

null reference Ignore

Naming and shadowing

field decl... Warning
local variable decl hides Warning
..include constructor On
type parameter hides.. Warning
method overridden but not pack.. Warning
interface method conflicts Warning

Deprecated and restricted API

All Warning

Unecessary code

local variable is never read Warning
parameter is never read Ignore
..check overriding.. On
unused import Warning
unused local or private member Ignore
unnecessary else statement Ignore
unnecessary cast Warning
unnecessary declaration of throw.. Ignore
unused break/continue label Warning

Generic types

Java 5 does not matter to us

Annotations

Java 5 does not matter to us

JavaDoc

To set these settings go to:

  • Java->Compiler->Java Doc
Process Javadoc comments On
malformed Javadoc comments Warning
Only consider members as visible as Private
..Report errors in tags On
..Report non-visible references On
..report deprecated references On
Missing Javadoc tags Warning
..Only consider members as visible as Private
..check overriding and implementing.. Off
Missing Javadoc comments Warning
..Only consider members as visible as Private
..check overriding .. Off

Back to parent page.