Module - Result codes

The aim of this tutorial is show the way, how to define result codes in custom module and how to expose list of codes on frontend.

  • You need to install CzechIdM 8.1.0 (and higher). We have CzechIdM installed for this tutorial on server http://localhost:8080/idm-backend.
  • Create an identity, which has permission to read installed backend modules (MODULE_READ permission). We are using the default admin:admin identity.

Source codes for this tutorial can be found in the example module

The first of all, we need to define result codes, which can be used, when some information has to be sent to client - as message or result of some operation. We will create new class in our module (example module is used here), which implements ResultCode interface:

package eu.bcvsolutions.idm.example.domain;
 
import org.springframework.http.HttpStatus;
import eu.bcvsolutions.idm.core.api.domain.ResultCode;
 
/**
 * Enum class for formatting response messages (mainly errors). 
 * Every enum contains a string message and corresponding https HttpStatus code.
 * 
 * Used http codes:
 * - 2xx - success
 * - 4xx - client errors (validations, conflicts ...)
 * - 5xx - server errors
 */
public enum ExampleResultCode implements ResultCode {
 
	EXAMPLE_CLIENT_ERROR(HttpStatus.BAD_REQUEST, "Example client error, bad value given [%s]"),
	EXAMPLE_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Example server error with parameter [%s]");
 
	private final HttpStatus status;
	private final String message;
 
	private ExampleResultCode(HttpStatus status, String message) {
		this.message = message;
		this.status = status;
	}
 
	public String getCode() {
		return this.name();
	}
 
	public String getModule() {
		return "example";
	}
 
	public HttpStatus getStatus() {
		return status;
	}
 
	public String getMessage() {
		return message;
	}	
}

Message ca be sent to clien as exception (example only):

@ResponseBody
	@RequestMapping(method = RequestMethod.GET, path = "/client-error")
	@ApiOperation(
			value = "Example client error", 
			notes= "Example client error with given parameter.",
			nickname = "exampleClientError", 
			tags={ ExampleController.TAG }, 
			authorizations = {
				@Authorization(SwaggerConfig.AUTHENTICATION_BASIC),
				@Authorization(SwaggerConfig.AUTHENTICATION_CIDMST)
			})
	public void clientError(
			@ApiParam(value = "Error parameter", example = "parameter", defaultValue = "value") 
			@RequestParam(required = false, defaultValue = "parameter") String parameter) {
		// lookout - ImmutableMap parameter values cannot be {@code null}
		throw new ResultCodeException(ExampleResultCode.EXAMPLE_CLIENT_ERROR, ImmutableMap.of("parameter", String.valueOf(parameter)));
	}

The better usage of result codes is as OperationResult - it's used for long running tasks, reports, provisioning operations etc.. Or simply DefaultResultModel with code in constructor can be used and returned to client. Component Advanced.OperationResult can be used for rendering OperationResult on frontend. Or the simpler component Basic.FlashMessage with FlashMessageManager#convertFromResultModel method, if only ResultModel has to be rendered - but OperationResult is prefered).

All defined result codes should be localized on frontend, add localization into locales:

...
  "error": {
    "EXAMPLE_SERVER_ERROR": {
      "title": "Example server error",
      "message": "Example server with parameter [{{parameter}}]."
    },
    "EXAMPLE_CLIENT_ERROR": {
      "title": "Example client error",
      "message": "Example client error, bad value given [{{parameter}}]."
    }
  },
...

Only en localization is shown here, complete localization files can be found in example module.

If localization on frontend is not found, then default message defined directly in ResultCode implemetation will be used.

Module can provide defined result codes to frontend, update module descriptor in your module, add:

...
public class ExampleModuleDescriptor extends PropertyModuleDescriptor {
...
        @Override
	public List<ResultCode> getResultCodes() {
		return Arrays.asList(ExampleResultCode.values());
	}
...

Go to menu Setting → Modules → Modules (backend), you will see new button in documentation column:

and after click on the button, modal will be shown: