blob: 0c150b789cd4f01a7440cd8442e3381e5bfb24bd [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>@DomainObject :: Apache Isis</title>
<link rel="canonical" href="https://isis.apache.org/refguide/2.0.0-M3/applib-ant/DomainObject.html">
<meta name="generator" content="Antora 2.2.0">
<link rel="stylesheet" href="../../../_/css/site.css">
<link rel="stylesheet" href="../../../_/css/site-custom.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i|Raleway:300,400,500,700,800|Montserrat:300,400,700" rel="stylesheet">
<link rel="home" href="https://isis.apache.org" title="Apache Isis">
<link rel="next" href="DomainObjectLayout.html" title="DomainObjectLayout">
<link rel="prev" href="Discriminator.html" title="Discriminator">
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://isis.apache.org">
<span class="icon">
<img src="../../../_/img/isis-logo-48x48.png"></img>
</span>
<span>Apache Isis</span>
</a>
<button class="navbar-burger" data-target="topbar-nav">
<span></span>
<span></span>
<span></span>
</button>
</div>
<div id="topbar-nav" class="navbar-menu">
<a class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">Quick Start</a>
<div class="navbar-dropdown">
<span class="navbar-item navbar-heading">Starter Apps</span>
<a class="navbar-item" href="../../../docs/2.0.0-M3/starters/helloworld.html">Hello World</a>
<a class="navbar-item" href="../../../docs/2.0.0-M3/starters/simpleapp.html">Simple App</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Demos &amp; Tutorials</span>
<a class="navbar-item" href="../../../docs/2.0.0-M3/demo/about.html">Demo App</a>
<a class="navbar-item" href="https://danhaywood.gitlab.io/isis-petclinic-tutorial-docs/petclinic/1.16.2/intro.html">Petclinic (tutorial)</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Resources</span>
<a class="navbar-item" href="../../../docs/2.0.0-M3/resources/cheatsheet.html">Cheatsheet</a>
<a class="navbar-item" href="../../../docs/2.0.0-M3/resources/icons.html">Icons</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">Guides</a>
<div class="navbar-dropdown">
<span class="navbar-item navbar-heading">Development</span>
<a class="navbar-item" href="../../../setupguide/2.0.0-M3/about.html">Setup Guide</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Core</span>
<a class="navbar-item" href="../../../userguide/2.0.0-M3/about.html">User Guide</a>
<a class="navbar-item" href="../../../refguide/2.0.0-M3/about.html">Reference Guide</a>
<a class="navbar-item" href="../../../testing/2.0.0-M3/about.html">Testing Guide</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">Libraries</a>
<div class="navbar-dropdown">
<span class="navbar-item navbar-heading">For Use in Apps</span>
<a class="navbar-item" href="../../../subdomains/2.0.0-M3/about.html">Subdomain Libraries</a>
<a class="navbar-item" href="../../../valuetypes/2.0.0-M3/about.html">Value Types</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Integrate between Apps</span>
<a class="navbar-item" href="../../../mappings/2.0.0-M3/about.html">Bounded Context Mapping Libraries</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Other</span>
<a class="navbar-item" href="../../../incubator/2.0.0-M3/about.html">Incubator</a>
<a class="navbar-item" href="../../../legacy/2.0.0-M3/about.html">Legacy</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">Components</a>
<div class="navbar-dropdown">
<span class="navbar-item navbar-heading">Viewers</span>
<a class="navbar-item" href="../../../vw/2.0.0-M3/about.html">Wicket UI</a>
<a class="navbar-item" href="../../../vro/2.0.0-M3/about.html">Restful Objects (REST)</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Security</span>
<a class="navbar-item" href="../../../security/2.0.0-M3/about.html">Security Guide</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Persistence</span>
<a class="navbar-item" href="../../../pjdo/2.0.0-M3/about.html">DataNucleus (JDO)</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Extensions</span>
<a class="navbar-item" href="../../../extensions/2.0.0-M3/about.html">Extensions Catalog</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">Support</a>
<div class="navbar-dropdown">
<span class="navbar-item navbar-heading">Contact</span>
<a class="navbar-item" href="../../../docs/2.0.0-M3/support/slack-channel.html">Slack</a>
<a class="navbar-item" href="../../../docs/2.0.0-M3/support/mailing-list.html">Mailing Lists</a>
<a class="navbar-item" href="https://issues.apache.org/jira/browse/ISIS">JIRA</a>
<a class="navbar-item" href="https://stackoverflow.com/questions/tagged/isis">Stack Overflow</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Releases</span>
<a class="navbar-item" href="../../../docs/2.0.0-M3/downloads/how-to.html">Downloads</a>
<a class="navbar-item" href="../../../relnotes/2.0.0-M3/about.html">Release Notes</a>
<a class="navbar-item" href="../../../docs/2.0.0-M3/archive/1-x.html">Archive (1.x)</a>
<hr class="navbar-divider"/>
<span class="navbar-item navbar-heading">Framework</span>
<a class="navbar-item" href="../../../conguide/2.0.0-M3/about.html">Contributors' Guide</a>
<a class="navbar-item" href="../../../comguide/2.0.0-M3/about.html">Committers' Guide</a>
<a class="navbar-item" href="../../../core/2.0.0-M3/about.html">Core Design</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="#">ASF</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="http://www.apache.org/">Apache Homepage</a>
<a class="navbar-item" href="https://www.apache.org/events/current-event">Events</a>
<a class="navbar-item" href="https://www.apache.org/licenses/">Licenses</a>
<a class="navbar-item" href="https://www.apache.org/security/">Security</a>
<a class="navbar-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
<a class="navbar-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a>
<hr class="navbar-divider"/>
<a class="navbar-item" href="https://whimsy.apache.org/board/minutes/Isis.html">PMC board minutes</a>
</div>
</div>
<a class="navbar-item" href="../../../docs/2.0.0-M3/about.html">
<span class="icon">
<img src="../../../_/img/home.png"></img>
</span>
</a>
</div>
</div>
</nav>
</header>
<div class="body ">
<div class="nav-container" data-component="refguide" data-version="2.0.0-M3">
<aside class="nav">
<div class="panels">
<div class="nav-panel-pagination">
<a class="page-previous" rel="prev" href="Discriminator.html" title="Discriminator"><span></span></a>
<a class="page-next" rel="next"
href="DomainObjectLayout.html" title="DomainObjectLayout"><span></span></a>
<!--
page.parent doesn't seem to be set...
<a class="page-parent" rel="prev" href="about.html" title="Discriminator"><span></span></a>
-->
</div>
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<h3 class="title"><a href="../about.html">Reference Guide</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="about.html">Annotations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Action.html">Action</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="ActionLayout.html">ActionLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Collection.html">Collection</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="CollectionLayout.html">CollectionLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Column.html">Column</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Digits.html">Digits</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Discriminator.html">Discriminator</a>
</li>
<li class="nav-item is-current-page" data-depth="2">
<a class="nav-link" href="DomainObject.html">DomainObject</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="DomainObjectLayout.html">DomainObjectLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="DomainService.html">DomainService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="DomainServiceLayout.html">DomainServiceLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Facets.html">Facets</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="HomePage.html">HomePage</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="MemberOrder.html">MemberOrder</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Mixin.html">Mixin</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="NotPersistent.html">NotPersistent.</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Nullable.html">Nullable</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="MinLength.html">MinLength</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Parameter.html">Parameter</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="ParameterLayout.html">ParameterLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Pattern.html">Pattern</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="PersistenceCapable.html">PersistenceCapable</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="PrimaryKey.html">PrimaryKey</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Programmatic.html">Programmatic</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Property.html">Property</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="PropertyLayout.html">PropertyLayout</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="IsisSessionScope.html">RequestScoped</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="Title.html">Title</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="ViewModel.html">ViewModel</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="XmlJavaTypeAdapter.html">XmlJavaTypeAdapter</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="XmlRootElement.html">XmlRootElement</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../applib-methods/about.html">Methods</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-methods/prefixes.html">Supporting Method Prefixes</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-methods/reserved.html">Reserved Methods</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-methods/lifecycle.html">Lifecycle Methods</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../applib-classes/about.html">Classes</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/events.html">Events</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/ViewModel.html"><code>ViewModel</code></a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/value-types.html">Value Types</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/spec.html">Specification pattern</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/i18n.html">i18n support</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/roles-mixins-contributees.html">Roles, Mixins and Contributees</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/utility.html">Utility Classes</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-classes/layout.html">Layout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../applib-svc/about.html">Domain Services</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/AcceptHeaderService.html">AcceptHeaderService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ApplicationFeatureRepository.html">ApplicationFeatureRepository</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/AuditerService.html">AuditerService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/BookmarkService.html">BookmarkService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/BookmarkUiService.html">BookmarkUiService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ClockService.html">ClockService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/CommandContext.html">CommandContext</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/CommandDtoProcessorService.html">CommandDtoProcessorService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/CommandExecutorService.html">CommandExecutorService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/CommandService.html">CommandService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ConfigurationMenu.html">ConfigurationMenu</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ConfigurationViewService.html">ConfigurationViewService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ContentMappingService.html">ContentMappingService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/DeepLinkService.html">DeepLinkService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/EmailNotificationService.html">EmailNotificationService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/EmailService.html">EmailService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ErrorReportingService.html">ErrorReportingService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/EventBusService.html">EventBusService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ExceptionRecognizerService.html">ExceptionRecognizerService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/FactoryService.html">FactoryService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/GridLoaderService.html">GridLoaderService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/GridService.html">GridService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/GridSystemService.html">GridSystemService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/HealthCheckService.html">HealthCheckService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/HintStore.html">HintStore</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/HomePageResolverService.html">HomePageResolverService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/InteractionContext.html">InteractionContext</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/JaxbService.html">JaxbService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/LayoutService.html">LayoutService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/LayoutServiceMenu.html">LayoutServiceMenu</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/LocaleProvider.html">LocaleProvider</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MenuBarsLoaderService.html">MenuBarsLoaderService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MenuBarsService.html">MenuBarsService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MessageService.html">MessageService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MetaModelService.html">MetamodelService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MetaModelServiceMenu.html">MetamodelServiceMenu</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/MetricsService.html">MetricsService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/PublisherService.html">PublisherService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/QueryResultsCache.html">QueryResultsCache</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/RepositoryService.html">RepositoryService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/RoutingService.html">RoutingService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/Scratchpad.html">Scratchpad</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ServiceInjector.html">ServiceInjector</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/ServiceRegistry.html">ServiceRegistry</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/SessionLoggingService.html">SessionLoggingService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/SudoService.html">SudoService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/SwaggerService.html">SwaggerService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/TableColumnOrderService.html">TableColumnOrderService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/TitleService.html">TitleService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/TranslationService.html">TranslationService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/TranslationsResolver.html">TranslationsResolver</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/TransactionService.html">TransactionService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/UrlEncodingService.html">UrlEncodingService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/UserProfileService.html">UserProfileService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/UserRegistrationService.html">UserRegistrationService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/UserService.html">UserService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/WrapperFactory.html">WrapperFactory</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/XmlService.html">XmlService</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../applib-svc/XmlSnapshotService.html">XmlSnapshotService</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../config/about.html">Configuration</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.applib.html">Applib</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.core.meta-model.html">Core MetaModel</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.core.meta-model.introspector.html">Core MetaModel Introspection</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.core.meta-model.validator.html">MetaModel Validator</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.core.runtime.html">Core Runtime Services configurations</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.core.runtime-services.html">Core Runtime Services configurations</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.security.shiro.html">Shiro Security Implementation</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.persistence.jdo-datanucleus.html">JDO DataNucleus</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.persistence.jdo-datanucleus.impl.html">DataNucleus Configuration</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.viewer.restfulobjects.html">Restful Objects Viewer</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.viewer.wicket.html">Wicket Viewer</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.extensions.html">Extensions</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.value-types.html">Value types</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.testing.html">Testing</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/isis.legacy.html">Legacy</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/resteasy.html">RestEasy Configuration</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../config/sections/Other.html">Other</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../schema/about.html">Schema</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../schema/mml.html">MetaModel</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../schema/cmd.html">Command</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../schema/ixn.html">Interaction</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../schema/chg.html">Changes</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../schema/common.html">Common</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="nav-panel-explore" data-panel="explore">
<div class="context">
<span class="title">Reference Guide</span>
<span class="version">2.0.0-M3</span>
</div>
<ul class="components">
<li class="component">
<span class="title"> </span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../docs/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">BC Mappings Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../mappings/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Committers' Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../comguide/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Contributors' Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../conguide/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Design Docs</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../core/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Extensions Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../extensions/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Incubator Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../incubator/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">JDO/DataNucleus</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../pjdo/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Legacy Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../legacy/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component is-current">
<span class="title">Reference Guide</span>
<ul class="versions">
<li class="version is-current is-latest">
<a href="../about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Release Notes</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../relnotes/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Restful Objects Viewer</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../vro/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Security Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../security/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Setup Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../setupguide/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Subdomains Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../subdomains/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Testing Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../testing/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">User Guide</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../userguide/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Value Types Catalog</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../valuetypes/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
<li class="component">
<span class="title">Wicket Viewer</span>
<ul class="versions">
<li class="version is-latest">
<a href="../../../vw/2.0.0-M3/about.html">2.0.0-M3</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
</div>
<main role="main">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<a href="../../../docs/2.0.0-M3/about.html" class="home-link"></a>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="../about.html">Reference Guide</a></li>
<li><a href="about.html">Annotations</a></li>
<li><a href="DomainObject.html">DomainObject</a></li>
</ul>
</nav>
<div class="edit-this-page"><a href="https://github.com/apache/isis/edit/2.0.0-M3/api/applib/src/main/adoc/modules/applib-ant/pages/DomainObject.adoc">Edit</a></div>
</div>
<article class="doc">
<a name="section-top"></a>
<h1 class="page"><code>@DomainObject</code></h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>The <code>@DomainObject</code> annotation applies to domain objects, collecting together all domain semantics within a single annotation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="main-api"><a class="anchor" href="#main-api"></a>Main API</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Inherited
@Target({
ElementType.TYPE,
ElementType.ANNOTATION_TYPE
})
@Retention(RetentionPolicy.RUNTIME)
@Component @Scope("prototype")
public @interface DomainObject {
Auditing auditing() <i class="conum" data-value="1"></i><b>(1)</b>
default Auditing.NOT_SPECIFIED;
Class&lt;?&gt; autoCompleteRepository() <i class="conum" data-value="2"></i><b>(2)</b>
default Object.class;
String autoCompleteAction() <i class="conum" data-value="3"></i><b>(3)</b>
default "autoComplete";
Bounding bounding() <i class="conum" data-value="4"></i><b>(4)</b>
default Bounding.NOT_SPECIFIED;
Editing editing() <i class="conum" data-value="5"></i><b>(5)</b>
default Editing.NOT_SPECIFIED;
String editingDisabledReason() <i class="conum" data-value="6"></i><b>(6)</b>
default "Disabled";
String mixinMethod() <i class="conum" data-value="7"></i><b>(7)</b>
default Mixin.DEFAULT_METHOD_NAME;
Nature nature() <i class="conum" data-value="8"></i><b>(8)</b>
default Nature.NOT_SPECIFIED;
String objectType() <i class="conum" data-value="9"></i><b>(9)</b>
default "";
Publishing publishing() <i class="conum" data-value="10"></i><b>(10)</b>
default Publishing.NOT_SPECIFIED;
// ...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><a href="#auditing"><code>auditing()</code></a>
<div class="paragraph">
<p>Indicates whether each of the changed properties of an object should be submitted to the registered
<a href="../applib-svc/AuditerService.html" class="page"><code>AuditerService</code></a>(s)</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><a href="#autoCompleteRepository"><code>autoCompleteRepository()</code></a>
<div class="paragraph">
<p>Nominate a method on a domain service to be used for looking up instances of the domain object</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td><a href="#autoCompleteAction"><code>autoCompleteAction()</code></a>
<div class="paragraph">
<p>Override the method name to use on the auto-complete repository</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td><a href="#bounding"><code>bounding()</code></a>
<div class="paragraph">
<p>Whether the number of instances of this domain class is relatively small (a "bounded" set), such that instances could be selected from a drop-down list box or similar.</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td><a href="#editing"><code>editing()</code></a>
<div class="paragraph">
<p>Whether the object&#8217;s properties and collections can be edited or not (ie whether the instance should be considered to be immutable)</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td><code>editingDisabledReason()</code>
<div class="paragraph">
<p>The default reason why the object&#8217;s properties and collections cannot be edited.</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td><a href="#mixinMethod"><code>mixinMethod()</code></a>
<div class="paragraph">
<p>How to recognize the "reserved" method name, meaning that the mixin&#8217;s own name will be inferred from the mixin type.
Typical examples are "exec", "execute", "invoke", "apply" and so on.
The default "reserved" method name is <code>$$</code>.</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td><a href="#nature"><code>nature()</code></a>
<div class="paragraph">
<p>Whether the domain object logically is an entity (part of the domain layer) or is a view model (part of the application layer); or is a mixin.
If an entity, indicates how its persistence is managed.</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td><a href="#objectType"><code>objectType()</code></a>
<div class="paragraph">
<p>Specify an alias for the domain class used to uniquely identify the object both within the Apache Isis runtime and externally</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="10"></i><b>10</b></td>
<td><a href="#publishing"><code>publishing()</code></a>
<div class="paragraph">
<p>Whether changes to the object should be published to the registered <a href="../applib-svc/PublisherService.html" class="page"><code>PublisherService</code></a>.</p>
</div></td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="entity-lifecycle-api"><a class="anchor" href="#entity-lifecycle-api"></a>Entity Lifecycle API</h2>
<div class="sectionbody">
<div class="paragraph">
<p>These attributes define the events to be fired throughout an the persistence lifecycle of a domain entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public @interface DomainObject {
// ...
Class&lt;? extends ObjectCreatedEvent&lt;?&gt;&gt;
createdLifecycleEvent() <i class="conum" data-value="1"></i><b>(1)</b>
default ObjectCreatedEvent.Default.class;
Class&lt;? extends ObjectPersistingEvent&lt;?&gt;&gt;
persistingLifecycleEvent() <i class="conum" data-value="2"></i><b>(2)</b>
default ObjectPersistingEvent.Default.class;
Class&lt;? extends ObjectPersistedEvent&lt;?&gt;&gt;
persistedLifecycleEvent() <i class="conum" data-value="3"></i><b>(3)</b>
default ObjectPersistedEvent.Default.class;
Class&lt;? extends ObjectLoadedEvent&lt;?&gt;&gt;
loadedLifecycleEvent() <i class="conum" data-value="4"></i><b>(4)</b>
default ObjectLoadedEvent.Default.class;
Class&lt;? extends ObjectUpdatingEvent&lt;?&gt;&gt;
updatingLifecycleEvent() <i class="conum" data-value="5"></i><b>(5)</b>
default ObjectUpdatingEvent.Default.class;
Class&lt;? extends ObjectUpdatedEvent&lt;?&gt;&gt;
updatedLifecycleEvent() <i class="conum" data-value="6"></i><b>(6)</b>
default ObjectUpdatedEvent.Default.class;
Class&lt;? extends ObjectRemovingEvent&lt;?&gt;&gt;
removingLifecycleEvent() <i class="conum" data-value="7"></i><b>(7)</b>
default ObjectRemovingEvent.Default.class;
// ...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><a href="#createdLifecycleEvent"><code>createdLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted to the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> whenever an instance is created</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><a href="#persistingLifecycleEvent"><code>persistingLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted to whenever an instance is about to be persisted</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td><a href="#persistedLifecycleEvent"><code>persistedLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted whenever an instance has just been persisted</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td><a href="#loadedLifecycleEvent"><code>loadedLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted whenever an instance has just been loaded from the datastore</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td><a href="#removingLifecycleEvent"><code>removingLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted whenever an instance is about to be deleted</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td><a href="#updatedlifecycleevent"><code>updatedLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted whenever an instance has just been updated</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td><a href="#updatingLifecycleEvent"><code>updatingLifecycleEvent()</code></a>
<div class="paragraph">
<p>The event type to be posted whenever an instance is about to be updated</p>
</div></td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="domain-events-api"><a class="anchor" href="#domain-events-api"></a>Domain Events API</h2>
<div class="sectionbody">
<div class="paragraph">
<p>These attributes define the events to be fired when a domain object&#8217;s members (its actions, properties and collections) are interacted with.</p>
</div>
<div class="paragraph">
<p>These attributes define the default event types; they can be overridden for each specific domain member.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public @interface DomainObject {
// ...
Class&lt;? extends ActionDomainEvent&lt;?&gt;&gt;
actionDomainEvent() <i class="conum" data-value="1"></i><b>(1)</b>
default ActionDomainEvent.Default.class;
Class&lt;? extends PropertyDomainEvent&lt;?,?&gt;&gt;
propertyDomainEvent() <i class="conum" data-value="2"></i><b>(2)</b>
default PropertyDomainEvent.Default.class;
Class&lt;? extends CollectionDomainEvent&lt;?,?&gt;&gt;
collectionDomainEvent() <i class="conum" data-value="3"></i><b>(3)</b>
default CollectionDomainEvent.Default.class;
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td><code>actionDomainEvent()</code>
<div class="paragraph">
<p>The event type to be posted to the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> whenever an action of the domain object is interacted with (if not overridden using <a href="Action.html#domainEvent" class="page"><code>@Action#domainEvent()</a></code>).</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><code>propertyDomainEvent()</code>
<div class="paragraph">
<p>The event type to be posted to the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> whenever a property of the domain object is interacted with (if not overridden using <a href="Property.html#domainEvent" class="page"><code>@Property#domainEvent()</a></code>).</p>
</div></td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td><code>collectionDomainEvent()</code>
<div class="paragraph">
<p>The event type to be posted to the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> whenever a collection of the domain object is interacted with (if not overridden using <a href="Collection.html#domainEvent" class="page"><code>@Collection#domainEvent()</a></code>).</p>
</div></td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
auditing=Auditing.ENABLED,
autoCompleteRepository=CustomerRepository.class
editing=Editing.ENABLED, <i class="conum" data-value="1"></i><b>(1)</b>
updatedLifecycleEvent=Customer.UpdatedEvent.class
)
public class Customer {
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>default value, so could be omitted</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="auditing"><a class="anchor" href="#auditing"></a><code>auditing()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>auditing</code> attribute indicates that if the object is modified, then each of its changed properties should be submitted to the registered <a href="../applib-svc/AuditerService.html" class="page"><code>AuditerService</code></a>(s).</p>
</div>
<div class="paragraph">
<p>The default value for the attribute is <code>AS_CONFIGURED</code>, meaning that the <a href="../config/sections/isis.applib.html#isis.applib.annotation.domain-object.auditing" class="page"><code>isis.applib.annotation.domain-object.auditing</code></a> configuration property is used to determine the whether the action is audited:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>all</code><br></p>
<div class="paragraph">
<p>all changed properties of objects are audited</p>
</div>
</li>
<li>
<p><code>none</code><br></p>
<div class="paragraph">
<p>no changed properties of objects are audited</p>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>If there is no configuration property in <code>application.properties</code> then auditing is automatically enabled for domain objects.</p>
</div>
<div class="paragraph">
<p>This default can be overridden on an object-by-object basis; if <code>auditing()</code> is set to <code>ENABLED</code> then changed properties of instances of the domain class are audited irrespective of the configured value; if set to <code>DISABLED</code> then the changed properties of instances are <em>not</em> audited, again irrespective of the configured value.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
auditing=Auditing.ENABLED <i class="conum" data-value="1"></i><b>(1)</b>
)
public class Customer {
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>because set to enabled, will be audited irrespective of the configured value.</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="autoCompleteRepository"><a class="anchor" href="#autoCompleteRepository"></a><code>autoCompleteRepository()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>autoCompleteRepository</code> attribute nominates a single method on a domain service as the fallback means for looking up instances of the domain object using a simple string.</p>
</div>
<div class="paragraph">
<p>For example, this might search for a customer by their name or number.
Or it could search for a country based on its ISO-3 code or user-friendly name.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>If you require additional control - for example restricting the returned results based on the object being interacted with - then use the <a href="../applib-methods/prefixes.html#autoComplete" class="page"><code>autoComplete&#8230;&#8203;()</code></a> supporting method instead.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
autoCompleteRepository=CustomerRepository.class
)
public class Customer {
....
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>where:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainService
public class CustomerRepository {
List&lt;Customer&gt; autoComplete(String search); <i class="conum" data-value="1"></i><b>(1)</b>
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>is assumed to be called "autoComplete", and accepts a single string</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="autoCompleteAction"><a class="anchor" href="#autoCompleteAction"></a><code>autoCompleteAction()</code></h3>
<div class="paragraph">
<p>As noted above, by default the method invoked on the repository is assumed to be called "autoComplete".
The optional <code>autoCompleteAction</code> attribute allows the method on the repository to be overridden.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
autoCompleteRepository=Customers.class,
autoCompleteAction="findByName"
)
public class Customer {
....
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>where in this case <code>findByName</code> might be an existing action already defined:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainService(nature = NatureOfService.VIEW)
public class Customers {
@Action(semantics=SemanticsOf.SAFE)
public List&lt;Customer&gt; findByName(
@MinLength(3) <i class="conum" data-value="1"></i><b>(1)</b>
@ParameterLayout(named="name")
String name);
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>end-user must enter minimum number of characters to trigger the query</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The autocomplete "action" can also be a regular method, annotated using <a href="Programmatic.html" class="page"><code>@Programmatic</code></a>.
That is, it does not need to be part of the metamodel:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainService(nature = NatureOfService.VIEW)
public class Customers {
@Programmatic
public List&lt;Customer&gt; findByName(
@MinLength(3)
String name);
...
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bounding"><a class="anchor" href="#bounding"></a><code>bounding</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>r</p>
</div>
<div class="paragraph">
<p>Some domain classes are immutable to the user, and moreover have only a fixed number of instances.
Often these are "reference" ("standing") data, or lookup data/pick lists.
Typical examples could include categories, countries, states, and tax or interest rate tables.</p>
</div>
<div class="paragraph">
<p>Where the number of instances is relatively small, ie bounded, then the <code>bounding</code> attribute can be used as a hint.
For such domain objects the framework will automatically allow instances to be selected; <a href="../../../vw/2.0.0-M3/about.html" class="page">Wicket viewer</a> displays these as a drop-down list.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
bounding=Bounding.BOUNDED,
editing=Editing.DISABLED <i class="conum" data-value="1"></i><b>(1)</b>
)
public class Currency {
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This attribute is commonly combined with <code>editing=DISABLED</code> to enforce the fact that reference data is immutable</td>
</tr>
</table>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>There is nothing to prevent you from using this attribute for regular mutable entities, and indeed this is sometimes worth doing during early prototyping.
However, if there is no realistic upper bound to the number of instances of an entity that might be created, generally you should use <a href="../applib-methods/prefixes.html#autoComplete" class="page"><code>autoComplete&#8230;&#8203;()</code></a> supporting method or the <a href="#autoCompleteRepository"><code>@DomainObject#autoCompleteRepository</code></a> attribute instead.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="createdLifecycleEvent"><a class="anchor" href="#createdLifecycleEvent"></a><code>createdLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a domain object is instantiated or otherwise becomes known to the framework, a "created" lifecycle event is fired.
This is typically when the <a href="../applib-svc/FactoryService.html" class="page"><code>FactoryService</code></a>'s <code>instantiate()</code> method is called.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the object just created.
The subscriber could then, for example, update the object, eg looking up state from some external datastore.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>It&#8217;s possible to instantiate objects without firing this lifecycle; just instantiate using its regular constructor, and then use the <code>ServiceRegistry</code>'s
<a href="../applib-svc/ServiceRegistry.html" class="page"><code>injectServicesInto(&#8230;&#8203;)</code></a> to manually inject any required domain services.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectCreatedEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>createdLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
createdLifecycleEvent=ToDoItem.CreatedEvent.class
)
public class ToDoItem {
public static class CreatedEvent
extends org.apache.isis.applib.events.lifecycle.ObjectCreatedEvent&lt;ToDoItem&gt; { }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers"><a class="anchor" href="#subscribers"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectCreatedEvent.class)
public void on(ObjectCreatedEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectCreatedEvent.class)
public void on(ToDoItem.ObjectCreatedEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events"><a class="anchor" href="#default-doop-and-noop-events"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>createdLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectCreatedEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.createdLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>createdLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectCreatedEvent.Doop</code> as such a subclass, so setting the <code>createdLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectCreatedEvent.Noop</code>; if <code>createdLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="editing"><a class="anchor" href="#editing"></a><code>editing()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>editing</code> attribute determines whether a domain object&#8217;s properties and collections are not editable (are read-only).</p>
</div>
<div class="paragraph">
<p>The default is <code>AS_CONFIGURED</code>, meaning that the <a href="../config/sections/isis.applib.html#isis.applib.annotation.domain-object.editing" class="page"><code>isis.applib.annotation.domain-object.editing</code></a>
configuration property is used to determine the whether the object is modifiable:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>true</code><br>
+ the object&#8217;s properties and collections are modifiable.</p>
</li>
<li>
<p><code>false</code><br>
+ the object&#8217;s properties and collections are read-only, ie <em>not</em> modifiable.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If there is no configuration property in <code>application.properties</code> then object are assumed to be modifiable.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In other words, editing can be disabled globally by setting the <a href="../config/sections/isis.applib.html#isis.applib.annotation.domain-object.editing" class="page"><code>isis.applib.adoc#isis.applib.annotation.domain-object.editing</code></a> configuration property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-ini hljs" data-lang="ini">isis.applib.annotation.domain-object.editing=false</code></pre>
</div>
</div>
<div class="paragraph">
<p>We recommend this setting; it will help drive out the underlying business operations (processes and procedures) that require objects to change; these can then be captured as business actions.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This default can be overridden on an object-by-object basis; if <code>editing()</code> is set to <code>ENABLED</code> then the object&#8217;s properties and collections are editable irrespective of the configured value; if set to <code>DISABLED</code> then the object&#8217;s properties and collections are not editable irrespective of the configured value.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
editing=Editing.DISABLED,
editingDisabledReason="Reference data, so cannot be modified"
)
public class Country {
...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="loadedLifecycleEvent"><a class="anchor" href="#loadedLifecycleEvent"></a><code>loadedLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a persistent domain object is loaded from the database, a "loaded" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object just loaded.
The subscriber could then, for example, update or default values on the object (eg to support on-the-fly migration scenarios).</p>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectLoadedEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>loadedLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
loadedLifecycleEvent=ToDoItem.LoadedEvent.class
)
public class ToDoItem {
public static class LoadedEvent extends
org.apache.isis.applib.events.lifecycle.ObjectLoadedEvent&lt;ToDoItem&gt; { }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-2"><a class="anchor" href="#subscribers-2"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectLoadedEvent.class)
public void on(ObjectLoadedEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectLoadedEvent.class)
public void on(ToDoItem.ObjectLoadedEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-2"><a class="anchor" href="#default-doop-and-noop-events-2"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>loadedLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectLoadedEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.loadedLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>loadedLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectLoadedEvent.Doop</code> as such a subclass, so setting the <code>loadedLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectLoadedEvent.Noop</code>; if <code>loadedLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mixinMethod"><a class="anchor" href="#mixinMethod"></a><code>mixinMethod()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>mixinMethod</code> attribute specifies the name of the method to be treated as a "reserved" method name, meaning that the mixin&#8217;s name should instead be inferred from the mixin&#8217;s type.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class Customer {
@DomainObject(
nature=Nature.MIXIN, <i class="conum" data-value="1"></i><b>(1)</b>
mixinMethod="execute" <i class="conum" data-value="2"></i><b>(2)</b>
)
public class placeOrder {
public Customer execute(Product p, int quantity) { <i class="conum" data-value="3"></i><b>(3)</b>
// ...
}
public String disableExecute() {
// ...
}
public String validate0Execute() {
// ...
}
}
)</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This is a mixin.<br>
Alternatively, could have used <a href="Mixin.html" class="page"><code>@Mixin</code></a>.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This mixin is using a non-standard method.<br>
Alternatively, could have used <a href="Mixin.html#method" class="page"><code>@Mixin#method()</code></a>.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Same name as the specified mixinMethod.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This allows all mixins to follow a similar convention, with the name of the mixin inferred entirely from its type ("placeOrder").</p>
</div>
<div class="paragraph">
<p>When invoked programmatically, the code reads:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">someCustomer.new placeOrder().execute(someProduct, 3);</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="nature"><a class="anchor" href="#nature"></a><code>nature()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>nature</code> attribute is used to characterize the domain object as either an entity (part of the domain layer) or as a view model (part of the application layer).
If the domain object should be thought of as an entity, it also captures how the persistence of that entity is managed.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(nature=Nature.VIEW_MODEL)
public class PieChartAnalysis {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Specifically, the nature must be one of:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>NOT_SPECIFIED,</code></p>
<div class="paragraph">
<p>(the default); specifies no paricular semantics for the domain class.</p>
</div>
</li>
<li>
<p><code>JDO_ENTITY</code></p>
<div class="paragraph">
<p>indicates that the domain object is an entity whose persistence is managed internally by Apache Isis, using the JDO/DataNucleus objectstore.</p>
</div>
</li>
<li>
<p><code>EXTERNAL_ENTITY</code></p>
<div class="paragraph">
<p>indicates that the domain objecct is a wrapper/proxy/stub (choose your term) to an entity that is managed by some related external system.
For example, the domain object may hold just the URI to a RESTful resource of some third party REST service, or the id of some system accessible over SOAP.</p>
</div>
<div class="paragraph">
<p>The identity of an external entity is determined solely by the state of entity&#8217;s properties.
The framework will automatically recreate the domain object each time it is interacted with.</p>
</div>
</li>
<li>
<p><code>INMEMORY_ENTITY</code></p>
<div class="paragraph">
<p>indicates that the domain object is a wrapper/proxy/stub to a "synthetic" entity, for example one that is constructed from some sort of internal memory data structure.</p>
</div>
<div class="paragraph">
<p>The identity of an inmemory entity is determined solely by the state of entity&#8217;s properties.
The framework will automatically recreate the domain object each time it is interacted with.</p>
</div>
</li>
<li>
<p><code>MIXIN</code></p>
<div class="paragraph">
<p>indicates that the domain object is part of the domain layer, and is contributing behaviour to objects of some other type as a mixin (also known as a trait).</p>
</div>
<div class="paragraph">
<p>Equivalent to annotating with <a href="Mixin.html" class="page"><code>@Mixin</code></a>.
For further discussion on using mixins, see <a href="../../../userguide/2.0.0-M3/fun/overview.html#mixins" class="page">mixins</a> in the user guide.</p>
</div>
</li>
<li>
<p><code>VIEW_MODEL</code></p>
<div class="paragraph">
<p>indicates that the domain object is conceptually part of the application layer, and exists to surfaces behaviour and/or state that is aggregate of one or more domain entities.</p>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Those natures that indicate the domain object is an entity (of some sort or another) mean then that the domain object is considered to be part of the domain model layer.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Under the covers Apache Isis' support for <code>VIEW_MODEL</code>, <code>EXTERNAL_ENTITY</code> and <code>INMEMORY_ENTITY</code> domain objects is identical; the state of the object is encoded into its internal OID (represented ultimately as its URL), and is recreated directly from that URL.</p>
</div>
<div class="paragraph">
<p>Because this particular implementation was originally added to Apache Isis in support of view models, the term was also used for the logically different external entities and inmemory entities.</p>
</div>
<div class="paragraph">
<p>The benefit of <code>nature()</code> is that it allows the developer to properly characterize the layer (domain vs application) that an entity lives, thus avoiding confusion as "view model" (the implementation technique) and "view model" (the application layer concept).</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>On the other hand, view models defined in this way do have some limitations; see <a href="ViewModel.html" class="page"><code>@ViewModel</code></a> for further discussion.</p>
</div>
<div class="paragraph">
<p>These limitations do <em>not</em> apply to <a href="../../../userguide/2.0.0-M3/fun/view-models.html#jaxb" class="page">JAXB</a> view models.
If you are using view models heavily, you may wish to restrict yourself to just the JAXB flavour.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="persistedLifecycleEvent"><a class="anchor" href="#persistedLifecycleEvent"></a><code>persistedLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a (just created, still transient) domain object has been saved (INSERTed in)to the database, a "persisted" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object.
The subscriber could then, for example, maintain an external datastore.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The object should <em>not</em> be modified during the persisted callback.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectPersistedEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>persistedLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
persistedLifecycleEvent=ToDoItem.PersistedEvent.class
)
public class ToDoItem {
public static class PersistedEvent extends
org.apache.isis.applib.events.lifecycle.ObjectPersistedEvent&lt;ToDoItem&gt; { }
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-3"><a class="anchor" href="#subscribers-3"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectPersistedEvent.class)
public void on(ObjectPersistedEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectPersistedEvent.class)
public void on(ToDoItem.ObjectPersistedEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-3"><a class="anchor" href="#default-doop-and-noop-events-3"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>persistedLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectPersistedEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.persistedLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>persistedLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectPersistedEvent.Doop</code> as such a subclass, so setting the <code>persistedLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectPersistedEvent.Noop</code>; if <code>persistedLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="persistingLifecycleEvent"><a class="anchor" href="#persistingLifecycleEvent"></a><code>persistingLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a (just created, still transient) domain object is about to be saved (INSERTed in)to the database, a "persisting" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object.
The subscriber could then, for example, update the object, or it could use it maintain an external datastore.
One possible application is to maintain a full-text search database using <a href="https://lucene.apache.org/">Apache Lucene</a> or similar.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Another use case is to maintain "last updated by"/"last updated at" properties.
While you can roll your own, note that the framework provides built-in support for this use case through the <a href="#applib-classes:classes/roles.adoc#Timestampable" class="page unresolved"><code>Timestampable</code></a> role interface.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectPersistingEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>persistingLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
persistingLifecycleEvent=ToDoItem.PersistingEvent.class
)
public class ToDoItem {
public static class PersistingEvent extends
org.apache.isis.applib.events.lifecycle.ObjectPersistingEvent&lt;ToDoItem&gt; { }
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-4"><a class="anchor" href="#subscribers-4"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectPersistingEvent.class)
public void on(ObjectPersistingEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectPersistingEvent.class)
public void on(ToDoItem.ObjectPersistingEvent ev) {
// ...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-4"><a class="anchor" href="#default-doop-and-noop-events-4"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>persistingLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectPersistingEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.persistingLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>persistingLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectPersistingEvent.Doop</code> as such a subclass, so setting the <code>persistingLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectPersistingEvent.Noop</code>; if <code>persistingLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="objectType"><a class="anchor" href="#objectType"></a><code>objectType()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>objectType</code> attribute is used to provide a unique alias for the object&#8217;s class name.</p>
</div>
<div class="paragraph">
<p>This value is used internally to generate a string representation of an objects identity (the <code>Oid</code>).
This can appear in several contexts, including:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>as the value of <code>Bookmark#getObjectType()</code> and in the <code>toString()</code> value of <code>Bookmark</code>
(see <a href="../applib-svc/BookmarkService.html" class="page"><code>BookmarkService</code></a>)</p>
</li>
<li>
<p>in the serialization of <code>OidDto</code> in the <a href="#refguide:schema:cmd">command</a> and <a href="../schema/ixn.html" class="page">interaction</a> schemas</p>
</li>
<li>
<p>in the URLs of the <a href="../../../vro/2.0.0-M3/about.html" class="page">RestfulObjects viewer</a></p>
</li>
<li>
<p>in the URLs of the <a href="../../../vw/2.0.0-M3/about.html" class="page">Wicket viewer</a></p>
</li>
<li>
<p>in XML snapshots generated by the <a href="../applib-svc/XmlSnapshotService.html" class="page"><code>XmlSnapshotService</code></a></p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="examples"><a class="anchor" href="#examples"></a>Examples</h3>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
objectType="orders.Order"
)
public class Order {
...
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="precedence"><a class="anchor" href="#precedence"></a>Precedence</h3>
<div class="paragraph">
<p>The rules of precedence are:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="Discriminator.html" class="page"><code>@Discriminator</code></a></p>
</li>
<li>
<p><code>@DomainObject#objectType</code></p>
</li>
<li>
<p><a href="PersistenceCapable.html" class="page"><code>@PersistenceCapable</code></a>, if at least the <code>schema</code> attribute is defined.</p>
<div class="paragraph">
<p>If both <code>schema</code> and <code>table</code> are defined, then the value is &#8220;schema.table&#8221;.
If only <code>schema</code> is defined, then the value is &#8220;schema.className&#8221;.</p>
</div>
</li>
<li>
<p>Fully qualified class name of the entity.</p>
</li>
</ol>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This might be obvious, but to make explicit: we recommend that you always specify an object type for your domain objects.</p>
</div>
<div class="paragraph">
<p>Otherwise, if you refactor your code (change class name or move package), then any externally held references to the OID of the object will break.
At best this will require a data migration in the database; at worst it could cause external clients accessing data through the <a href="../../../vro/2.0.0-M3/about.html" class="page">Restful Objects</a> viewer to break.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>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.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="publishing"><a class="anchor" href="#publishing"></a><code>publishing()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>publishing</code> attribute determines whether and how a modified object instance is published via the registered implementation of <a href="../applib-svc/PublisherService.html" class="page"><code>PublisherService</code></a>.</p>
</div>
<div class="paragraph">
<p>A common use case is to notify external "downstream" systems of changes in the state of the Apache Isis application.</p>
</div>
<div class="paragraph">
<p>The default value for the attribute is <code>AS_CONFIGURED</code>, meaning that the <a href="../config/sections/isis.applib.html#isis.applib.annotation.domain-object.publishing" class="page"><code>isis.applib.annotation.domain-object.publishing</code></a> configuration property is used to determine the whether the domain object&#8217;s changes are published:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>all</code></p>
<div class="paragraph">
<p>all changed objects are published</p>
</div>
</li>
<li>
<p><code>none</code></p>
<div class="paragraph">
<p>no changed objects are published</p>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>If there is no configuration property in <code>application.properties</code> then publishing is automatically disabled for domain objects.</p>
</div>
<div class="paragraph">
<p>This default can be overridden on an object-by-object basis; if <code>publishing()</code> is set to <code>ENABLED</code> then changed instances of the domain class are published irrespective of the configured value; if set to <code>DISABLED</code> then the changed instances are <em>not</em> published, again irrespective of the configured value.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject(
publishing=Publishing.ENABLED <i class="conum" data-value="1"></i><b>(1)</b>
)
public class InterestRate {
...
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>because set to enabled, will be published irrespective of the configured value.</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="see-also"><a class="anchor" href="#see-also"></a>See also</h3>
<div class="paragraph">
<p>This attribute is also supported for:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="Action.html#publishing" class="page">actions</a></p>
<div class="paragraph">
<p>where it controls whether action invocations are published as events, and for</p>
</div>
</li>
<li>
<p><a href="Property.html#publishing" class="page">properties</a></p>
<div class="paragraph">
<p>where it controls whether property edits are published as events.</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="removingLifecycleEvent"><a class="anchor" href="#removingLifecycleEvent"></a><code>removingLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>r
:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a> . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:</p>
</div>
<div class="paragraph">
<p>Whenever a (persistent) domain object is about to be removed (DELETEd) from the database, a "removing" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object.
The subscriber could then, for example, could use it maintain an external datastore.
One possible application is to maintain a full-text search database using <a href="https://lucene.apache.org/">Apache Lucene</a> or similar.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Another use case is to maintain "last updated by"/"last updated at" properties.
While you can roll your own, note that the framework provides built-in support for this use case through the <a href="#applib-classes:classes/roles.adoc#Timestampable" class="page unresolved"><code>Timestampable</code></a> role interface.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectRemovingEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>removingLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
removingLifecycleEvent=ToDoItem.RemovingEvent.class
)
public class ToDoItem {
public static class RemovingEvent extends
org.apache.isis.applib.events.lifecycle.ObjectRemovingEvent&lt;ToDoItem&gt; { }
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-5"><a class="anchor" href="#subscribers-5"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectRemovingEvent.class)
public void on(ObjectRemovingEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectRemovingEvent.class)
public void on(ToDoItem.ObjectRemovingEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-5"><a class="anchor" href="#default-doop-and-noop-events-5"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>removingLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectRemovingEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.removingLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>removingLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectRemovingEvent.Doop</code> as such a subclass, so setting the <code>removingLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectRemovingEvent.Noop</code>; if <code>removingLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="updatingLifecycleEvent"><a class="anchor" href="#updatingLifecycleEvent"></a><code>updatingLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a (persistent) domain object has been modified and is about to be updated to the database, an "updating" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object.
The subscriber could then, for example, update the object, or it could use it maintain an external datastore.
One possible application is to maintain a full-text search database using <a href="https://lucene.apache.org/">Apache Lucene</a> or similar.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Another use case is to maintain "last updated by"/"last updated at" properties.
While you can roll your own, note that the framework provides built-in support for this use case through the
<a href="#applib-classes:classes/roles.adoc#Timestampable" class="page unresolved"><code>Timestampable</code></a> role interface.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectUpdatingEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>updatingLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
updatingLifecycleEvent=ToDoItem.UpdatingEvent.class
)
public class ToDoItem {
public static class UpdatingEvent extends
org.apache.isis.applib.events.lifecycle.ObjectUpdatingEvent&lt;ToDoItem&gt; { }
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-6"><a class="anchor" href="#subscribers-6"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectUpdatingEvent.class)
public void on(ObjectUpdatingEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectUpdatingEvent.class)
public void on(ToDoItem.ObjectUpdatingEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-6"><a class="anchor" href="#default-doop-and-noop-events-6"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>updatingLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectUpdatingEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.updatingLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>updatingLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectUpdatingEvent.Doop</code> as such a subclass, so setting the <code>updatingLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectUpdatingEvent.Noop</code>; if <code>updatingLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="updatedLifecycleEvent"><a class="anchor" href="#updatedLifecycleEvent"></a><code>updatedLifecycleEvent()</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whenever a (persistent) domain object has been modified and has been updated in the database, an "updated" lifecycle event is fired.</p>
</div>
<div class="paragraph">
<p>Subscribers subscribe through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a> and can use the event to obtain a reference to the domain object.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The object should <em>not</em> be modified during the updated callback.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>By default the event raised is <code>ObjectUpdatedEvent.Default</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObject
public class ToDoItemDto {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The purpose of the <code>updatedLifecycleEvent</code> attribute is to allows a custom subclass to be emitted instead.
A similar attribute is available for other lifecycle events.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@DomainObjectLayout(
updatedLifecycleEvent=ToDoItem.UpdatedEvent.class
)
public class ToDoItem {
public static class UpdatedEvent extends
org.apache.isis.applib.events.lifecycle.ObjectUpdatedEvent&lt;ToDoItem&gt; { }
// ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The benefit is that subscribers can be more targeted as to the events that they subscribe to.</p>
</div>
<div class="sect2">
<h3 id="subscribers-7"><a class="anchor" href="#subscribers-7"></a>Subscribers</h3>
<div class="paragraph">
<p>Subscribers (which must be domain services) subscribe to events posted through the <a href="../applib-svc/EventBusService.html" class="page"><code>EventBusService</code></a>.</p>
</div>
<div class="paragraph">
<p>Subscribers can be either coarse-grained (if they subscribe to the top-level event type):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ObjectUpdatedEvent.clas)
public void on(ObjectUpdatedEvent ev) {
if(ev.getSource() instanceof ToDoItem) {
...
}
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>or can be fine-grained (by subscribing to specific event subtypes):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.ObjectUpdatedEvent.class)
public void on(ToDoItem.ObjectUpdatedEvent ev) {
...
}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="default-doop-and-noop-events-7"><a class="anchor" href="#default-doop-and-noop-events-7"></a>Default, Doop and Noop events</h3>
<div class="paragraph">
<p>If the <code>updatedLifecycleEvent</code> attribute is not explicitly specified (is left as its default value, <code>ObjectUpdatedEvent.Default</code>), then the framework will, by default, post an event.</p>
</div>
<div class="paragraph">
<p>If this is not required, then the <code>isis.reflector.facet.domainObjectAnnotation.updatedLifecycleEvent.postForDefault</code> configuration property can be set to "false"; this will disable posting.</p>
</div>
<div class="paragraph">
<p>On the other hand, if the <code>updatedLifecycleEvent</code> has been explicitly specified to some subclass, then an event will be posted.
The framework provides <code>ObjectUpdatedEvent.Doop</code> as such a subclass, so setting the <code>updatedLifecycleEvent</code> attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.</p>
</div>
<div class="paragraph">
<p>And, conversely, the framework also provides <code>ObjectUpdatedEvent.Noop</code>; if <code>updatedLifecycleEvent</code> attribute is set to this class, then no event will be posted.</p>
</div>
</div>
</div>
</div>
</article>
<aside class="article-aside toc" role="navigation">
<p class="toc-title">On this page</p>
<div id="article-toc"></div>
</aside>
</main>
</div>
<footer class="footer">
<div class="content">
<div class="copyright">
<p>
Copyright © 2010~2020 The Apache Software Foundation, licensed under the Apache License, v2.0.
<br/>
Apache, the Apache feather logo, Apache Isis, and the Apache Isis project logo are all trademarks of The Apache Software Foundation.
</p>
</div>
<div class="revision">
<p>Revision: SNAPSHOT</p>
</div>
</div>
</footer>
<script src="../../../_/js/site.js"></script>
<script async src="../../../_/js/vendor/highlight.js"></script>
<script src="../../../_/js/vendor/jquery-3.4.1.min.js"></script>
<script src="../../../_/js/vendor/jquery-ui-1.12.1.custom.widget-only.min.js"></script>
<script src="../../../_/js/vendor/jquery.tocify.min.js"></script>
<script>
$(function() {
$("#article-toc").tocify( {
showEffect: "slideDown",
hashGenerator: "pretty",
hideEffect: "slideUp",
selectors: "h2, h3",
scrollTo: 120,
smoothScroll: true,
theme: "jqueryui",
highlightOnScroll: true
} );
});
</script>
</body>
</html>