Java Code Standards for Liferay

Created: 13 April 2020  Modified:

This article is meant to provide guidance for myself and others on what I would recommend from my coding experience using Liferay. we will focus on Java initially and expand into Javascript. Most of this experience is carried forward from Liferay 6.2 but looks to work well with Liferay 7.1. We ran both versions using OpenJDK 1.8.

Coding Standards for Liferay

Our standards will be based on Effective Java 2nd Edition available from Amazon and from Alibris. A 3rd edition is available. It is for newer OpenJDKs and will not be referenced here. Most of our deviations from the book are an effort to make unit testing faster and easier to achieve.

SOLID

Keep in mind the principles represented by the acronym SOLID.

Unit Test All Logic

This includes a single if statement, loop, stream, lambda, switch, etc.

Avoid Integration Testing

Do not place logic in Liferay classes that need the Liferay environment to be tested. Move any logic to a separate class.

Use Dependency Inversion/Injection

In practice we use a manual version of Dependency Injection. Liferay based classes are used to instantiate all needed objects, without introducing logic. Then create a separate class to which you will pass all the needed objects to the constructor.

Validate All Constructor Parameters

All constructor parameters should be checked for nulls except where nulls are desireable. Other acceptable values should be checked for. In all cases throw and IllegalArgumentException where values do not meet expectations. Pass a string argument to the exception providing additional information, when needed. Liferay code cannot be relied upon to guarantee non-null values. Using the Optional class is the desired pattern. Example below.

Check constructor parameters

public class MyClass {
  private static final Log LOG = LogFactoryUtil.getLog(MyClass.class);
  
  private MyLambda<String, Connection> myLambda;
  
  public MyClass(myLambda<String, Connection> myLambda) {
  	this.myLambda=Optional.ofNullable(myLambda).orElseThrow(IllegalArgumentException::new);
    this.myLambda=Optional.ofNullable(myLambda)
  				.orElseThrow(() -> new IllegalArgumentException("Lambda cannot be null"));  
  }
}

Favor Streams over Loops

When using lists, streams are to be favored over for loops or while loops.

Stream examples

myList.stream().filter(Objects::nonNull).collect(Collectors.toList());
layouts.stream().filter(Objects::nonNull).mapToLong(Layout::getPlid).forEach(this::updateLayout);
String[] oldPortletIdsArray = feedKeysMap.keySet().stream().toArray(String[]::new);
Optional<DDMStructure> fieldStructure = ddmStructures.stream().filter(Objects::nonNull)
							.filter(structure -> structure.hasField(fieldName)).findFirst();
entity.getMetaDataFields().stream()
				.filter(this::isAllowedField)
				.sorted((field1, field2) -> field1.getLabel().compareToIgnoreCase(field2.getLabel()))
				.map(this::getMetaFieldJSON)
				.collect(JSONArray::new, JSONArray::put, JSONArray::put);

Code Relationships Should Look Like a Star

If you favor composition over inheritance then your code should look like a star when diagramed. It shouldn’t look like a hiking trail or highway.

Good Diagram



Good Diagram
tags: liferay - java - code - standard - code standard
   Less Is More