@DomainService

Indicates that the class should be automatically recognized as a domain service.

Also indicates whether the domain service acts as a repository for an entity, and menu ordering UI hints.

API

DomainService.java
@interface DomainService {
  NatureOfService nature() default NatureOfService.VIEW;     (1)
  @AliasFor(annotation = Named.class, attribute = "value")
String objectType() default "";     (2)
  @AliasFor(annotation = Named.class, attribute = "value")
String logicalTypeName() default "";     (3)
}
1 nature

The nature of this service, either in the UI or REST only

2 objectType

deprecated:

use #logicalTypeName() instead

Synonym for #logicalTypeName() .

3 logicalTypeName

The logical name of this object’s type, that uniquely and fully qualifies it. The logical name is analogous to - but independent of - the actual fully qualified class name. eg. sales.CustomerService for a class 'org.mycompany.services.CustomerService'

Members

nature

The nature of this service, either in the UI or REST only

objectType

deprecated:

use #logicalTypeName() instead

Synonym for #logicalTypeName() .

logicalTypeName

The logical name of this object’s type, that uniquely and fully qualifies it. The logical name is analogous to - but independent of - the actual fully qualified class name. eg. sales.CustomerService for a class 'org.mycompany.services.CustomerService'

This value, if specified, is used in the serialized form of the object’s Bookmark . A Bookmark is used by the framework to uniquely identify an object over time (same concept as a URN). Otherwise, if not specified, the fully qualified class name is used instead.

Usage Notes

Object Alias

The logicalTypeName() element is used to provide a unique alias for the domain service’s class name.

This value is used internally to generate a string representation of an service identity (the Oid). This can appear in several contexts, including:

Example

For example:

@DomainService(
    logicalTypeName="orders.OrderMenu"
)
public class OrderMenu {
    ...
}

Precedence

The rules of precedence are:

  1. @DomainService#logicalTypeName

  2. getId()

  3. The fully qualified class name.

This might be obvious, but to make explicit: we recommend that you always specify an object type for your domain services.

Otherwise, if you refactor your code (change class name or move package), then any externally held references to the OID of the service will break. At best this will require a data migration in the database; at worst it could cause external clients accessing data through the Restful Objects viewer to break.

If the object type is not unique across all domain classes then the framework will fail-fast and fail to boot. An error message will be printed in the log to help you determine which classes have duplicate object tyoes.

Nature of Service

The nature() element indicates the intent of the actions defined within the domain service:

  • VIEW

    The default; the service’s actions appear on menu bars, can be contributed, appear in the REST API

  • REST

    The service’s actions are intended only to be listed in the REST API exposed by the RestfulObjects viewer.

The actual class name of the domain service is only rendered for the VIEW natures.

For example:

@DomainService( nature=NatureOfService.VIEW )
@RequiredArgsConstructor(onConstructor_ = {@Inject} )
public class Loans {                                   (1)

    private final LoanRepository loanRepository;       (2)

    @Action(semantics=SemanticsOf.SAFE)
    public List<Loan> findOverdueLoans() {
        // ...
    }
}
1 name is intended to be rendered in the UI
2 it’s common for domain-layer domain services to be injected into presentation layer services.

For services that do not need to appear in the UI and do not need to be invoked using WrapperFactory (in other words, do not need to be part of the metamodel), you can declare the service using Spring’s @Service, @Repository or @Component annotations.

For example:

@Repository
public class LoanRepository {
    public List<Loan> findLoansFor(Borrower borrower) {
        // ...
    }
}