Skip to content

Java and JSP

General conventions

  • Try to separate data ‘Entity’ classes, which contain data from logic classes which operate on the data and IO classes which manage the persistence of the data.
  • Use the same names for the Java entity (data) classes for the associated PostgreSQL table.
  • Use the singular version in both cases (not the plural version for tables). Except where we have to avoid SQL reserved words e.g. the ‘Users’ and 'Orders' tables.
  • Use the same name for the Java entity (data) class member variables and the associated column in the PostgreSQL table.
  • Be aware that while the Java classes may be case-sensitive camel-case, the names in the Postgres schema and SQL logic are case-insensitive.
  • Use that name as the prefix for the IO classes which manage the JDBC persistence of the data between the entity class and PostgreSQL table.
  • One of the goals is to carry names for the same entity across the system. So a global 'find in files' type text search will tend to find all the related elements.
  • So this means we tend not to use lower with under_score naming convention in the database and peripheral languages such as Javascript.
  • Prefer not prefixing argument variables with a e.g. prefer orderId over aOrderId.
  • Also, contrary to the other projects, prefer capitalising only the first letter of an acronym when naming variables e.g. prefer orderId over orderID.

Specific conventions

Java

  • Follow the conventions described here: https://www.Javatpoint.com/Java-naming-conventions
  • Package names are all lowercase.
  • Class names are camel case starting with an uppercase char and no underscores.
  • Method names are camel case starting with a lowercase char and no underscores.
  • Class member variables are camel case, starting with a lowercase prefix 'm' and no underscores.
  • Class member variables are private or protected (not public), with public set() and get() methods to access them.
  • Method parameter names are camel case, no longer start with a lowercase prefix 'a', and contain no underscores.
  • Local variables are camel case starting with a lowercase char, no special prefix char or underscores.
  • Static ‘constant’ variables are all UPPER_CASE with underscores.
  • The maximum size of DB character columns is set in Java as a public static variable in the related entity class.
  • Use Java base types for numeric, boolean variables wherever possible, e.g int and not Integer.
  • Try to avoid nullable numeric columns in PostgreSQL - as null is awkward to translate to Java base types.
  • Use Java long (not int) for entity id variables. Although historically we have used int for many entity ids.
  • We tend to use -1, to represent "not set" in id into or long variables.
  • Use the full name for id variables consistently across the system. e.g. primary key TradeId is used in the Trade class, in other variables and in foreign-key and references - like Bid.TradeId.

Examples

As a clean example, the core of our Voucher processing involves these elements;

  • com.bidorbuy.bobe.voucher - Java package
  • Voucher - Java entity class
  • Voucher - PostgreSQL table
  • VoucherIO - Java JDBC persistence class
  • VoucherTransaction - Java entity class
  • VoucherTransaction - PostgreSQL table
  • VoucherTransactionIO - Java JDBC persistence class
  • VoucherInterface - the collections of logic methods for managing Vouchers and VoucherTransactions

Please Note: For historical reasons, we tend to have much of our logic in static methods in classes with the ‘Interface’ suffix, e.g. VoucherInterface.mySampleMethod().

This is not ideal as the classes are not actually Java ‘Interfaces'.

If we ever refactor this convention we would do it in a more ‘Spring’-like way, using something like the 'Service’ suffix, and implement Service classes and singletons and not use static methods. As we now do for our IO classes. e.g. VoucherService.getInstance().mySampleMethod(). But for now we will stick with our convention for consistency.

Using the Voucher.Java as an example:

package com.bidorbuy.bobe.voucher;

import com.bidorbuy.bobe.enumlistitem.VoucherStatus;
import com.bidorbuy.bobe.enumlistitem.VoucherType;
import com.bidorbuy.bobe.user.HasUserId;

import Java.time.LocalDate;
import Java.time.LocalDateTime;

/**
 * Entity class representing a Voucher definition record.
 */
public class Voucher implements HasUserId {
//---- GENERATED CODE START -----------

  //------------------------------------
  // Attribute Name Definitions
  public static final String VOUCHER = "Voucher";
  public static final String VOUCHERID = "Voucher_VoucherId";
  public static final String USERID = "Voucher_UserId";
  public static final String VOUCHERTYPE = "Voucher_VoucherType";
  public static final String STATUS = "Voucher_Status";
  public static final String AMOUNT = "Voucher_Amount";
  public static final String USEDAMOUNT = "Voucher_UsedAmount";
  public static final String CREATIONTIME = "Voucher_CreationTime";
  public static final String LASTMODIFIEDTIME = "Voucher_LastModifiedTime";
  public static final String EXPIRYDATE = "Voucher_ExpiryDate";
  public static final String ASSIGNEDTIME = "Voucher_AssignedTime";
  public static final String VOUCHERGROUPID = "Voucher_VoucherGroupId";
  public static final String VOUCHERCODE = "Voucher_VoucherCode";
  public static final String FROMUSERID = "Voucher_FromUserId";
  public static final String ADMINUSERID = "Voucher_AdminUserId";
  public static final String ORDERID = "Voucher_OrderId";
  public static final String PAYMENTTRANSACTIONID = "Voucher_PaymentTransactionId";
  public static final String CLIENTDEVICEID = "Voucher_ClientDeviceId";
  public static final String IPADDRESS = "Voucher_IPAddress";
  public static final String ADMINNOTE = "Voucher_AdminNote";
  public static final String SYSTEMNOTE = "Voucher_SystemNote";


  //------------------------------------
  // Attribute Set & Get Methods

  /** Sets the value for the attribute VoucherId.
   * @param long  the value to set.
   */
  public void setVoucherId(long aValue) { mVoucherId = aValue; }

  /** Returns the value for the attribute VoucherId.
   * @return long  the VoucherId attribute.
   */
  public long getVoucherId() { return mVoucherId; }

  /** Sets the value for the attribute UserId.
   * @param int  the value to set.
   */
  public void setUserId(int aValue) { mUserId = aValue; }

  /** Returns the value for the attribute UserId.
   * @return int  the UserId attribute.
   */
  public int getUserId() { return mUserId; }

  /** Sets the value for the attribute VoucherType.
   * @param VoucherType  the value to set.
   */
  public void setVoucherType(VoucherType aValue) { mVoucherType = aValue; }

  /** Returns the value for the attribute VoucherType.
   * @return VoucherType  the VoucherType attribute.
   */
  public VoucherType getVoucherType() { return mVoucherType; }

  /** Sets the value for the attribute Status.
   * @param VoucherStatus  the value to set.
   */
  public void setStatus(VoucherStatus aValue) { mStatus = aValue; }

  /** Returns the value for the attribute Status.
   * @return VoucherStatus  the Status attribute.
   */
  public VoucherStatus getStatus() { return mStatus; }

  /** Sets the value for the attribute Amount.
   * @param double  the value to set.
   */
  public void setAmount(double aValue) { mAmount = aValue; }

  /** Returns the value for the attribute Amount.
   * @return double  the Amount attribute.
   */
  public double getAmount() { return mAmount; }

  /** Sets the value for the attribute UsedAmount.
   * @param double  the value to set.
   */
  public void setUsedAmount(double aValue) { mUsedAmount = aValue; }

  /** Returns the value for the attribute UsedAmount.
   * @return double  the UsedAmount attribute.
   */
  public double getUsedAmount() { return mUsedAmount; }

  /** Sets the value for the attribute CreationTime.
   * @param LocalDateTime  the value to set.
   */
  public void setCreationTime(LocalDateTime aValue) { mCreationTime = aValue; }

  /** Returns the value for the attribute CreationTime.
   * @return LocalDateTime  the CreationTime attribute.
   */
  public LocalDateTime getCreationTime() { return mCreationTime; }

  /** Sets the value for the attribute LastModifiedTime.
   * @param LocalDateTime  the value to set.
   */
  public void setLastModifiedTime(LocalDateTime aValue) { mLastModifiedTime = aValue; }

  /** Returns the value for the attribute LastModifiedTime.
   * @return LocalDateTime  the LastModifiedTime attribute.
   */
  public LocalDateTime getLastModifiedTime() { return mLastModifiedTime; }

  /** Sets the value for the attribute ExpiryDate.
   * @param LocalDate  the value to set.
   */
  public void setExpiryDate(LocalDate aValue) { mExpiryDate = aValue; }

  /** Returns the value for the attribute ExpiryDate.
   * @return LocalDate  the ExpiryDate attribute.
   */
  public LocalDate getExpiryDate() { return mExpiryDate; }

  /** Sets the value for the attribute AssignedTime.
   * @param LocalDateTime  the value to set.
   */
  public void setAssignedTime(LocalDateTime aValue) { mAssignedTime = aValue; }

  /** Returns the value for the attribute AssignedTime.
   * @return LocalDateTime  the AssignedTime attribute.
   */
  public LocalDateTime getAssignedTime() { return mAssignedTime; }

  /** Sets the value for the attribute VoucherGroupId.
   * @param int  the value to set.
   */
  public void setVoucherGroupId(int aValue) { mVoucherGroupId = aValue; }

  /** Returns the value for the attribute VoucherGroupId.
   * @return int  the VoucherGroupId attribute.
   */
  public int getVoucherGroupId() { return mVoucherGroupId; }

  /** Sets the value for the attribute VoucherCode.
   * @param String  the value to set.
   */
  public void setVoucherCode(String aValue) { mVoucherCode = aValue; }

  /** Returns the value for the attribute VoucherCode.
   * @return String  the VoucherCode attribute.
   */
  public String getVoucherCode() { return mVoucherCode; }

  /** Sets the value for the attribute FromUserId.
   * @param int  the value to set.
   */
  public void setFromUserId(int aValue) { mFromUserId = aValue; }

  /** Returns the value for the attribute FromUserId.
   * @return int  the FromUserId attribute.
   */
  public int getFromUserId() { return mFromUserId; }

  /** Sets the value for the attribute AdminUserId.
   * @param int  the value to set.
   */
  public void setAdminUserId(int aValue) { mAdminUserId = aValue; }

  /** Returns the value for the attribute AdminUserId.
   * @return int  the AdminUserId attribute.
   */
  public int getAdminUserId() { return mAdminUserId; }

  /** Sets the value for the attribute OrderId.
   * @param int  the value to set.
   */
  public void setOrderId(int aValue) { mOrderId = aValue; }

  /** Returns the value for the attribute OrderId.
   * @return int  the OrderId attribute.
   */
  public int getOrderId() { return mOrderId; }

  /** Sets the value for the attribute PaymentTransactionId.
   * @param int  the value to set.
   */
  public void setPaymentTransactionId(int aValue) { mPaymentTransactionId = aValue; }

  /** Returns the value for the attribute PaymentTransactionId.
   * @return int  the PaymentTransactionId attribute.
   */
  public int getPaymentTransactionId() { return mPaymentTransactionId; }

  /** Sets the value for the attribute ClientDeviceId.
   * @param long  the value to set.
   */
  public void setClientDeviceId(long aValue) { mClientDeviceId = aValue; }

  /** Returns the value for the attribute ClientDeviceId.
   * @return long  the ClientDeviceId attribute.
   */
  public long getClientDeviceId() { return mClientDeviceId; }

  /** Sets the value for the attribute IPAddress.
   * @param String  the value to set.
   */
  public void setIPAddress(String aValue) { mIPAddress = aValue; }

  /** Returns the value for the attribute IPAddress.
   * @return String  the IPAddress attribute.
   */
  public String getIPAddress() { return mIPAddress; }

  /** Sets the value for the attribute AdminNote.
   * @param String  the value to set.
   */
  public void setAdminNote(String aValue) { mAdminNote = aValue; }

  /** Returns the value for the attribute AdminNote.
   * @return String  the AdminNote attribute.
   */
  public String getAdminNote() { return mAdminNote; }

  /** Sets the value for the attribute SystemNote.
   * @param String  the value to set.
   */
  public void setSystemNote(String aValue) { mSystemNote = aValue; }

  /** Returns the value for the attribute SystemNote.
   * @return String  the SystemNote attribute.
   */
  public String getSystemNote() { return mSystemNote; }


  /** Returns a string representation of the the entity object.
   *
   * @return String.
   *
   */
  public String toString() {

    StringBuffer sb = new StringBuffer();

    sb.append("VoucherId").append("=").append(mVoucherId).append(", ");
    sb.append("UserId").append("=").append(mUserId).append(", ");
    sb.append("VoucherType").append("=").append(mVoucherType).append(", ");
    sb.append("Status").append("=").append(mStatus).append(", ");
    sb.append("Amount").append("=").append(mAmount).append(", ");
    sb.append("UsedAmount").append("=").append(mUsedAmount).append(", ");
    sb.append("CreationTime").append("=").append(mCreationTime).append(", ");
    sb.append("LastModifiedTime").append("=").append(mLastModifiedTime).append(", ");
    sb.append("ExpiryDate").append("=").append(mExpiryDate).append(", ");
    sb.append("AssignedTime").append("=").append(mAssignedTime).append(", ");
    sb.append("VoucherGroupId").append("=").append(mVoucherGroupId).append(", ");
    sb.append("VoucherCode").append("=").append(mVoucherCode).append(", ");
    sb.append("FromUserId").append("=").append(mFromUserId).append(", ");
    sb.append("AdminUserId").append("=").append(mAdminUserId).append(", ");
    sb.append("OrderId").append("=").append(mOrderId).append(", ");
    sb.append("PaymentTransactionId").append("=").append(mPaymentTransactionId).append(", ");
    sb.append("ClientDeviceId").append("=").append(mClientDeviceId).append(", ");
    sb.append("IPAddress").append("=").append(mIPAddress).append(", ");
    sb.append("AdminNote").append("=").append(mAdminNote).append(", ");
    sb.append("SystemNote").append("=").append(mSystemNote);

    return sb.toString();
  }

//---- GENERATED CODE END -----------

  /** Voucher Default Constructor
  */
  public Voucher() { }

  // Constants
  public static final int UNSPECIFIED = -1;
  public static final int VOUCHERCODE_SIZE = 50;
  public static final int IPADDRESS_SIZE = 40;
  public static final int ADMINNOTE_SIZE = 500;
  public static final int SYSTEMNOTE_SIZE = 500;

  // Attributes
  private long mVoucherId = UNSPECIFIED;
  private int mUserId = UNSPECIFIED;
  private VoucherType mVoucherType = VoucherType.UNSPECIFIED;
  private VoucherStatus mStatus = VoucherStatus.UNSPECIFIED;
  private double mAmount = 0.00;
  private double mUsedAmount = 0.00;
  private LocalDateTime mCreationTime = LocalDateTime.now();
  private LocalDateTime mLastModifiedTime = LocalDateTime.now();
  private LocalDate mExpiryDate = LocalDate.now();
  private LocalDateTime mAssignedTime = null;
  private int mVoucherGroupId = UNSPECIFIED;
  private String mVoucherCode = null;
  private int mFromUserId = UNSPECIFIED;
  private int mAdminUserId = UNSPECIFIED;
  private int mOrderId = UNSPECIFIED;
  private int mPaymentTransactionId = UNSPECIFIED;
  private long mClientDeviceId = UNSPECIFIED;
  private String mIPAddress = "";
  private String mAdminNote = null;
  private String mSystemNote = null;
}

Tools and assistance

EntityClassGenerator

The EntityClassGenerator will generate a complete standardised entity class based on just the class outline and member variables code. If member variables are adjusted the EntityClassGenerator can be rerun to produce an adjusted class.

The generated code includes getXX(), setXX(), toString() methods. And static member name strings to use as parameter names.

e.g.

$> cat Bird.Java

package com.bidorbuy.bobe.bird;

/**
 * Entity class representing a Bird.
 */
public class Bird  {

  /**
  */
  public Bird() { }

  // Constants
  public static final int UNSPECIFIED = -1;
  public static final int NAME_SIZE = 100;

  // Attributes
  private long mBirdId = UNSPECIFIED;
  private String mName = null;
  private double mWingSpanCm = 0.00;
}


$> bash ~/Workspaces/bob/bobe/scripts/runide.sh com.bidorbuy.tools.EntityClassGenerator Bird.Java

J/J 24/08/22 11:04:21 Running job with normal-memory: 'com.bidorbuy.tools.EntityClassGenerator Bird.Java
Generating Code for the following Attributes

long mBirdId
String mName
double mWingSpanCm
J/J 24/08/22 11:04:21 Completed job!


$> cat Bird.Java
package com.bidorbuy.bobe.voucher;

/**
 * Entity class representing a Bird.
 */
public class Bird  {
//---- GENERATED CODE START -----------

  //------------------------------------
  // Attribute Name Definitions
  public static final String BIRD = "Bird";
  public static final String BIRDID = "Bird_BirdId";
  public static final String NAME = "Bird_Name";
  public static final String WINGSPANCM = "Bird_WingSpanCm";


  //------------------------------------
  // Attribute Set & Get Methods

  /** Sets the value for the attribute BirdId.
   * @param long  the value to set.
   */
  public void setBirdId(long aValue) { mBirdId = aValue; }

  /** Returns the value for the attribute BirdId.
   * @return long  the BirdId attribute.
   */
  public long getBirdId() { return mBirdId; }

  /** Sets the value for the attribute Name.
   * @param String  the value to set.
   */
  public void setName(String aValue) { mName = aValue; }

  /** Returns the value for the attribute Name.
   * @return String  the Name attribute.
   */
  public String getName() { return mName; }

  /** Sets the value for the attribute WingSpanCm.
   * @param double  the value to set.
   */
  public void setWingSpanCm(double aValue) { mWingSpanCm = aValue; }

  /** Returns the value for the attribute WingSpanCm.
   * @return double  the WingSpanCm attribute.
   */
  public double getWingSpanCm() { return mWingSpanCm; }


  /** Returns a string representation of the the entity object.
   *
   * @return String.
   *
   */
  public String toString() {

    StringBuffer sb = new StringBuffer();

    sb.append("BirdId").append("=").append(mBirdId).append(", ");
    sb.append("Name").append("=").append(mName).append(", ");
    sb.append("WingSpanCm").append("=").append(mWingSpanCm);

    return sb.toString();
  }

//---- GENERATED CODE END -----------

  /**
  */
  public Bird() { }

  // Constants
  public static final int UNSPECIFIED = -1;
  public static final int NAME_SIZE = 100;

  // Attributes
  private long mBirdId = UNSPECIFIED;
  private String mName = null;
  private double mWingSpanCm = 0.00;
}

JDBCObjectIO

JDBC entity IO classes should be inherited from JDBCObjectIO<T>.

The class can then define the specific logic to identify insert, update and select columns and mapping logic.

And the underlying JDBCObjectIO will automatically provide a variety of insert, update and select operations to manage persistence between the Java entity object and the related table.

package com.bidorbuy.bobe.bird;

import com.bidorbuy.bobe.jdbc.JDBCObjectIO;
import com.bidorbuy.bobe.jdbc.JDBCObjectReader;
import com.bidorbuy.bobe.jdbc.JDBCObjectWriter;
import com.bidorbuy.bobe.jdbc.JDBCUtility;

import Java.sql.PreparedStatement;
import Java.sql.ResultSet;
import Java.sql.SQLException;

/**
 * A class for the IO between Bird objects and the Bird database table.
 */
public class BirdIO extends JDBCObjectIO<Bird> {

  private static BirdIO mInstance;
  static {
    mInstance = new BirdIO();
    mInstance
    .setTableName("Bird")
    .setTableAlias("b")
    .setInsertSQL("insert into Bird (BirdId, Name, WingSpanCm) values (?,?,?)")
    .setInsertJDBCObjectWriter(
        new JDBCObjectWriter<Bird>() {
          public int writeObject(PreparedStatement aPreparedStatement, Bird aBird) throws SQLException {
            if(aBird.getBirdId() == Bird.UNSPECIFIED) {
              aBird.setBirdId(JDBCUtility.getNextSequenceIdLong(aPreparedStatement.getConnection(), "BirdId_SEQ"));
            }
            int param = 1;
            aPreparedStatement.setLong(param++, aBird.getBirdId());
            aPreparedStatement.setString(param++, StringUtility.truncate(aBird.getName(), BIRD.NAME_SIZE));
            aPreparedStatement.setDouble(param++, aBird.getWingSpanCm());
            return param;
          }
        })
    .setUpdateSQL("update Bird set Name=?, WingSpanCm=? where BirdId=?")
    .setUpdateJDBCObjectWriter(
        new JDBCObjectWriter<Bird>() {
          public int writeObject(PreparedStatement aPreparedStatement, Bird aBird) throws SQLException {
            int param = 1;
            aPreparedStatement.setString(param++, StringUtility.truncate(aBird.getName(), BIRD.NAME_SIZE));
            aPreparedStatement.setDouble(param++, aBird.getWingSpanCm());
            aPreparedStatement.setLong(param++, aBird.getBirdId());
            return param;
          }
        })
    .setSelectColumnsSQL("b.BirdId, b.Name, b.WingSpanCm")
    .setJDBCObjectReader(
        new JDBCObjectReader<Bird>() {
          public Bird readObject(ResultSet aResultSet) throws SQLException {
            Bird Bird = new Bird();
            int columnIndex = 1;
            Bird.setBirdId(aResultSet.getLong(columnIndex++));
            Bird.setName(aResultSet.getString(columnIndex++));
            Bird.setWingSpanCm(aResultSet.getDouble(columnIndex++));
            return Bird;
          }
        }
        );
  }

  /**
   *
   * @return
   */
  public static BirdIO getInstance() {
    return mInstance;
  }

  /**
   *
   */
  private BirdIO() {
  }

}

List, ListItem and EnumListItem

Where possible represent new static or semi-static lists with entries in List and ListItem tables.

And instead of using a coded Java enum, generate a specialised class based on a List which inherits from EnumListItem.

The advantages are:

  • Avoid creating additional tables for each new type of list.
  • List and ListItem are cached in Java memory for fast access.
  • Our generated EnumListItem classes are more powerful than conventional Java enums.
  • We end up with a consistent sense of List and ENum values in Java and in PostgreSQL plsql logic - all derived from the common List and ListItem values.