@Property
Collects together all the domain semantics for the property of a domain object.
API
@interface Property {
Class<? extends CommandDtoProcessor> commandDtoProcessor() default CommandDtoProcessor.class; (1)
Publishing commandPublishing() default Publishing.NOT_SPECIFIED; (2)
Class<? extends PropertyDomainEvent<?, ?>> domainEvent() default PropertyDomainEvent.Default.class; (3)
@AliasFor(annotation = DomainObject.class, attribute = "editing")
Editing editing() default Editing.NOT_SPECIFIED; (4)
@AliasFor(annotation = DomainObject.class, attribute = "editingDisabledReason")
String editingDisabledReason() default ""; (5)
@AliasFor(annotation = DomainObject.class, attribute = "entityChangePublishing")
Publishing entityChangePublishing() default Publishing.NOT_SPECIFIED; (6)
Publishing executionPublishing() default Publishing.NOT_SPECIFIED; (7)
String fileAccept() default ""; (8)
int maxLength() default -1; (9)
Snapshot snapshot() default Snapshot.NOT_SPECIFIED; (10)
Class<? extends Specification>[] mustSatisfy() default {}; (11)
Optionality optionality() default Optionality.NOT_SPECIFIED; (12)
Projecting projecting() default Projecting.NOT_SPECIFIED; (13)
String regexPattern() default ""; (14)
int regexPatternFlags() default 0; (15)
String regexPatternReplacement() default "Doesn't match pattern"; (16)
QueryDslAutoCompletePolicy queryDslAutoComplete() default QueryDslAutoCompletePolicy.EXCLUDE; (17)
}
1 | commandDtoProcessor
The CommandDtoProcessor to process this command’s DTO. |
2 | commandPublishing
Whether property edits, captured as Command s, should be published to CommandSubscriber s. |
3 | domainEvent
Indicates that changes to the property that should be posted to the org.apache.causeway.applib.services.eventbus.EventBusService event bus using a custom (subclass of) PropertyDomainEvent . |
4 | editing
Whether the properties of this domain object can be edited, or collections of this object be added to/removed from. |
5 | editingDisabledReason
If #editing() is set to Editing#DISABLED , then the reason to provide to the user as to why this property cannot be edited. |
6 | entityChangePublishing
When set to Publishing#DISABLED , vetoes publishing of updates for this property. Otherwise has no effect, except when using Publishing#ENABLED to override an inherited property annotation, which is a supported use-case. |
7 | executionPublishing
Whether Execution s (triggered property edits), should be dispatched to ExecutionSubscriber s. |
8 | fileAccept |
9 | maxLength
The maximum entry length of a field. |
10 | snapshot
Indicates whether the property should be included or excluded from mementos. |
11 | mustSatisfy
The Specification (s) to be satisfied by this property. |
12 | optionality
Whether this property is optional or is mandatory (ie required). |
13 | projecting
If set to Projecting#PROJECTED projected , then indicates that the owner of this property is a view model which is a projection of some other entity, and that the property holds a reference to that "underlying". |
14 | regexPattern
Regular expression pattern that a value should conform to, and can be formatted as. |
15 | regexPatternFlags
Pattern flags, as per java.util.regex.Pattern#compile(String, int) . |
16 | regexPatternReplacement
Replacement text for the pattern in generated error message. |
17 | queryDslAutoComplete
Whether to use the value of this property for autocompletes. |
Members
commandDtoProcessor
The CommandDtoProcessor to process this command’s DTO.
The processor itself is used by ContentMappingServiceForCommandDto and ContentMappingServiceForCommandsDto to dynamically transform the DTOs.
commandPublishing
Whether property edits, captured as Command s, should be published to CommandSubscriber s.
domainEvent
Indicates that changes to the property that should be posted to the org.apache.causeway.applib.services.eventbus.EventBusService event bus using a custom (subclass of) PropertyDomainEvent .
Subscribers of this event can interact with the business rule checking (hide, disable, validate) and its modification (before and after).
For example:
public static class StartDateChanged extends PropertyDomainEvent { ... } @Property(domainEvent=StartDateChanged.class) public LocalDate getStartDate() { ...}
This subclass must provide a no-arg constructor; the fields are set reflectively.
editing
Whether the properties of this domain object can be edited, or collections of this object be added to/removed from.
Note that non-editable objects can nevertheless have actions invoked upon them.
editingDisabledReason
If #editing() is set to Editing#DISABLED , then the reason to provide to the user as to why this property cannot be edited.
If left empty (default), no reason is given.
entityChangePublishing
When set to Publishing#DISABLED , vetoes publishing of updates for this property. Otherwise has no effect, except when using Publishing#ENABLED to override an inherited property annotation, which is a supported use-case.
Relates to DomainObject#entityChangePublishing() , which controls whether entity-change-publishing is enabled for the corresponding entity type.
executionPublishing
Whether Execution s (triggered property edits), should be dispatched to ExecutionSubscriber s.
fileAccept
The value should be of the form "file_extension|audio/|video/|image/*|media_type".
Note that this does not prevent the user from uploading some other file type; rather it merely defaults the file type in the file open dialog.
maxLength
The maximum entry length of a field.
The default value ( -1
) indicates that no maxLength has been specified.
this will usually be supplemented by a JDO or JPA-specific annotation to indicate length of the column in the table to whic the entity is mapped. |
snapshot
Indicates whether the property should be included or excluded from mementos.
To ensure that the property is actually not persisted in the objectstore, also annotate with the JDO annotation javax.jdo.annotations.NotPersistent
mustSatisfy
The Specification (s) to be satisfied by this property.
If more than one is provided, then all must be satisfied (in effect "AND"ed together).
optionality
Whether this property is optional or is mandatory (ie required).
this will usually be supplmented by a JDO or JPA-specific annotation to specify the nullability of the corresponding column in the table to which the owning entity is mapped. |
projecting
If set to Projecting#PROJECTED projected , then indicates that the owner of this property is a view model which is a projection of some other entity, and that the property holds a reference to that "underlying".
This is used to automatically redirect any bookmarks to the view model (projection) to instead be directed at the underlying entity.
Only one such property should be marked as being a projection with a view model.
regexPatternFlags
Pattern flags, as per java.util.regex.Pattern#compile(String, int) .
The default value, 0
, means that no flags have been specified.
queryDslAutoComplete
Whether to use the value of this property for autocompletes.
The minimum number of characters can be specified by annotating the the containing entity with DomainObject#queryDslAutoCompleteMinLength() . The number of returned rows can also be limited using DomainObject#queryDslAutoCompleteLimitResults() .
Moreover, additional criteria (predicates) can be specified for the auto-complete query, by annotating the containing entity with DomainObject#queryDslAutoCompleteAdditionalPredicateRepository() and (if required) DomainObject#queryDslAutoCompleteAdditionalPredicateMethod() .
if DomainObject#autoCompleteRepository() (and DomainObject#autoCompleteMethod() ) have been specified, then these take precedence of the query DSL auto-complete. |
this feature requires that the querydsl-xxx module (for JDO or JPA as required) is included as part of the application manifest. Otherwise, no autocomplete will be generated.
|
this feature only applies to entities, not to view models. Only persisted properties should be annotated. |
Examples
For example:
@DomainObject
public class Customer {
public static class EmailSpecification extends AbstractSpecification<String> {
public String satisfiesSafely(String proposed) {
return EmailUtil.ensureValidEmail(proposed); (1)
}
}
@javax.jdo.annotations.Column(allowsNull="true") (2)
@Property(
maxLength=30,
mustSatisfy=EmailSpecification.class,
regexPattern = "(\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+",
regexPatternFlags=Pattern.CASE_INSENSITIVE
)
public String getEmailAddress() { /* ... */ }
public void setEmailAddress(String emailAddress) { /* ... */ }
...
}
1 | the (fictitious) EmailUtil.ensureValid(…) (omitted for brevity) returns a string explaining if an email is invalid |
2 | generally use instead of the @Property#optionality attribute |
The annotation is one of a handful (others including @Collection, @CollectionLayout and @PropertyLayout) that can also be applied to the field, rather than the getter method. This is specifically so that boilerplate-busting tools such as Project Lombok can be used. |
Usage Notes
Mandatory vs optional
By default, Apache Causeway assumes that all properties of an domain object or view model are required (mandatory). The optionality() attribute allows this to be relaxed. The attribute is also supported for parameters.
That said, properties are most commonly defined on persistent domain objects (entities), in which case the JDO @Column should be specified. Apache Causeway can infer the maxLength directly from the equivalent @Column#length() annotation.
That said, properties are most commonly defined on persistent domain objects (entities), in which case the JDO @Column will in any case need to be specified.
Apache Causeway can infer the optionality
semantic directly from the equivalent @Column#allowsNull()
annotation/attribute.
For example:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@javax.jdo.annotations.Column(allowsNull="true")
@Getter @Setter
private String middleInitial;
// ...
}
In this case there is no need for the @Property#optionality
attribute.
Mismatched defaults
If the @Column#allowsNull
attribute is omitted and the `@Property#optionality() attribute is also omitted, then note that Causeway' defaults and JDO’s defaults differ.
Specifically, Causeway always assumes properties are mandatory, whereas JDO specifies that primitives are mandatory, but all reference types are optional.
When Apache Causeway initializes it checks for these mismatches during its metamodel validation phase, and will fail to boot ("fail-fast") if there is a mismatch.
The fix is usually to add the @Column#allowsNull()
annotation/attribute.
Superclass inheritance type
There is one case (at least) it may be necessary to annotate the property with both @Column#allowsNull
and also @Property#optionality()
.
If the property is logically mandatory and is in a subclass, but the mapping of the class hierarchy is to store both the superclass and subclass(es) into a single table (ie a "roll-up" mapping using javax.jdo.annotations.InheritanceStrategy#SUPERCLASS_TABLE
), then JDO requires that the property is annotated as @Column#allowsNull="true"
: its value will be not defined for other subclasses.
In this case we therefore require both annotations.
@javax.jdo.annotations.PersistenceCapable
@javax.jdo.annotations.Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public abstract class PaymentMethod {
...
}
@javax.jdo.annotations.PersistenceCapable
@javax.jdo.annotations.Inheritance(strategy = InheritanceStrategy.SUPERCLASS_TABLE)
public class CreditCardPaymentMethod extends PaymentMethod {
private String cardNumber;
@javax.jdo.annotations.Column(allowsNull="true")
@Property(optionality=Optionality.MANDATORY)
public String getCardNumber() { return this.cardNumber; }
public void setCardNumber(String cardNumber) { this.cardNumber = cardNumber; }
...
}
Alternatively, you could rely on the fact that Apache Causeway never looks at fields (whereas JDO does) and move the JDO annotation to the field:
@javax.jdo.annotations.PersistenceCapable
@javax.jdo.annotations.Inheritance(strategy = InheritanceStrategy.SUPERCLASS_TABLE)
public class CreditCardPaymentMethod extends PaymentMethod {
@javax.jdo.annotations.Column(allowsNull="true")
private String cardNumber;
public String getCardNumber() { return this.cardNumber; }
public void setCardNumber(String cardNumber) { this.cardNumber = cardNumber; }
// ...
}
However this at first glance this might be read as meaning that the property is optional whereas Apache Causeway' default (required) applies.
Non-persistent properties
Of course, not every property is persistent (it could instead be derived), and neither is every domain object an entity (it could be a view model).
For these non persistable properties the optionality
attribute is still required.
For example:
public class Customer {
@javax.jdo.annotation.NotPersistent (1)
@Property(optionality=Optionality.OPTIONAL)
public String getFullName() { (2)
// ...
}
public void setFullName(String fullName) { (3)
// ...
}
// ...
}
1 | a non persisted (derived) property |
2 | implementation would most likely derive full name from constituent parts (eg first name, middle initial, last name) |
3 | implementation would most likely parse the input and update the constituent parts |
The attribute has no meaning for a primitive type such as |
The values for the attribute are simply OPTIONAL
or MANDATORY
.
It is also possible to specify optionality using @Nullable annotation. |
Editing
The editing() element can be used to prevent a property from being modified or cleared, ie to make it read-only.
The related editingDisabledReason() element specifies a hard-coded reason why the property cannot be modified directly.
Whether a property is enabled or disabled depends upon these factors:
-
whether the domain object has been configured as immutable through the @DomainObject#editing() element
-
else (that is, if the domain object’s editability is specified as being
AS_CONFIGURED
), then the value of the 'causeway.applib.annotation.domain-object.editing' configuration property.If set to
false
, then the object’s properties (and collections) are not editable -
else, the value of the
@Property(editing=…)
attribute itself -
else, the result of invoking any supporting disable…() supporting methods
Thus, to make a property read-only even if the object would otherwise be editable, use:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@Property(
editing=Editing.DISABLED,
editingDisabledReason =
"The credit rating is derived from multiple factors"
)
@Getter @Setter
private int initialCreditRating;
}
Maximum (string) length
The maxLength() attribute applies only to String
properties, indicating the maximum number of characters that the user may enter (for example in a text field in the UI).
The attribute It is ignored if applied to properties of any other type.
That said, properties are most commonly defined on persistent domain objects (entities), in which case the JDO @Column will in any case need to be specified.
Apache Causeway can infer the maxLength
semantic directly from the equivalent @Column#length()
annotation/attribute.
For example:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@javax.jdo.annotations.Column(length=30)
@Getter @Setter
private String firstName;
// ...
}
In this case there is therefore no need for the @Property#maxLength
attribute.
Non-persistent properties
Of course, not every property is persistent (it could instead be derived), and neither is every domain object an entity (it could be a view model).
For these non persistable properties the maxLength
attribute is still required.
For example:
public class Customer {
@javax.jdo.annotation.NotPersistent (1)
@Property(maxLength=100)
public String getFullName() { /* ... */ } (2)
public void setFullName(String fullName) { /* ... */ } (3)
...
}
1 | a non persisted (derived) property |
2 | implementation would most likely derive full name from constituent parts (eg first name, middle initial, last name) |
3 | implementation would most likely parse the input and update the constituent parts |
See also
This attribute can also be applied to parameters.
Declarative validation
The mustSatisfy() element allows arbitrary validation to be applied to properties using an (implementation of a) org.apache.causeway.applib.spec.Specification
object.
The attribute is also supported on parameters.
The specification implementations can (of course) be reused between properties and parameters. |
The Specification
is consulted during validation, being passed the proposed value.
If the proposed value fails, then the value returned is the used as the invalidity reason.
For example:
public class StartWithCapitalLetterSpecification
extends AbstractSpecification<String> { (1)
public String satisfiesSafely(String proposed) {
return "".equals(proposed)
? "Empty string"
: !Character.isUpperCase(proposed.charAt(0))
? "Does not start with a capital letter"
: null;
}
}
1 | the AbstractSpecification class conveniently handles type-safety and dealing with null values. |
where:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@Property(mustSatisfy=StartWithCapitalLetterSpecification.class)
@Getter @Setter
private String firstName;
// ...
}
It is also possible to provide translatable reasons.
Rather than implement Specification
, instead implement Specification2
which defines the API:
public interface Specification2 extends Specification {
public TranslatableString satisfiesTranslatable(Object obj); (1)
}
1 | Return null if specification satisfied, otherwise the reason as a translatable string |
With Specification2
there is no need to implement the inherited satifies(Object)
; that method will never be called.
Projections
A common use case for view models is to act as a projection of some underlying entity, to decorate that entity with additional behaviour (or remove existing behaviour) for some particular business context.
Very often the object that is of interest to the end-user is the underlying entity, not the view model per se. If the view model is displayed within a table (on a home page, say), then when the user clicks the entity/icon link for the view model, they will in fact want to drill-down to the underlying entity and skip the view model completely.
The projecting() element allows the view model to indicate which of its properties holds a reference to the underlying entity of which it is a projection.
For example:
@DomainObject(nature=VIEW_MODEL)
public InvoiceSummary {
@Property(
projecting = Projecting.PROJECTED, (1)
hidden = Where.EVERYWHERE (2)
)
@Getter @Setter
private Invoice invoice;
public LocalDate getDueDate() { (3)
return invoice.getDueDate();
}
...
}
1 | indicates that this property holds a reference to the underlying entity |
2 | the underlying entity is typically (though not necessarily) hidden |
3 | typical implementation of the properties of the underlying entity that are being projected in the view model. |
Domain events
Whenever a domain object (or list of domain objects) is to be rendered, the framework fires off multiple domain events for every property, collection and action of the domain object. In the cases of the domain object’s properties, the events that are fired are:
-
hide phase: to check that the property is visible (has not been hidden)
-
disable phase: to check that the property is usable (has not been disabled)
-
validate phase: to check that the property’s arguments are valid (to modify/clear its value)
-
pre-execute phase: before the modification of the property
-
post-execute: after the modification of the property
Subscribers subscribe through the EventBusService and can influence each of these phases.
By default the event raised is PropertyDomainEvent.Default
.
For example:
import lombok.Getter;
import lombok.Setter;
public class ToDoItem {
@Property()
@Getter @Setter
private LocalDate dueBy;
// ...
}
The domainEvent() element allows a custom subclass to be emitted allowing more precise subscriptions (to those subclasses) to be defined instead.
For example:
import lombok.Getter;
import lombok.Setter;
public class ToDoItem {
public static class DueByChangedEvent
extends PropertyDomainEvent<ToDoItem, LocalDate> { } (1)
@Property(domainEvent=ToDoItem.DueByChangedEvent)
@Getter @Setter
private LocalDate dueBy;
// ...
}
1 | inherit from PropertyDomainEvent<T,P> where T is the type of the domain object being interacted with, and P is the type of the property (LocalDate in this example) |
The benefit is that subscribers can be more targeted as to the events that they subscribe to.
The framework provides a no-arg constructor and will initialize the domain event using (non-API) setters rather than through the constructor. This substantially reduces the boilerplate required in subclasses because no explicit constructor is required. |
Subscribers
Subscribers (which must be domain services) subscribe to events posted through the EventBusService.
Subscribers can be either coarse-grained (if they subscribe to the top-level event type):
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(PropertyDomainEvent.class)
public void on(PropertyDomainEvent ev) {
// ...
}
}
or can be fine-grained (by subscribing to specific event subtypes):
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
@EventListener(ToDoItem.DueByChangedEvent.class)
public void on(ToDoItem.DueByChangedEvent ev) {
// ...
}
}
The subscriber’s method is called (up to) 5 times:
-
whether to veto visibility (hide)
-
whether to veto usability (disable)
-
whether to veto execution (validate)
-
steps to perform prior to the property being modified
-
steps to perform after the property has been modified.
The subscriber can distinguish these by calling ev.getEventPhase()
.
Thus the general form is:
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class SomeSubscriber {
public void on(PropertyDomainEvent ev) {
switch(ev.getEventPhase()) {
case HIDE: (1)
break;
case DISABLE: (2)
break;
case VALIDATE: (3)
break;
case EXECUTING:
break;
case EXECUTED:
break;
}
}
}
1 | call ev.hide() or ev.veto("") to hide the property |
2 | call ev.disable("…") or ev.veto("…") to disable the property |
3 | call ev.invalidate("…") or ev.veto("…") if proposed new value for property is invalid |
It is also possible to abort the transaction during the executing or executed phases by throwing an exception.
If the exception is a subtype of RecoverableException
then the exception will be rendered as a user-friendly warning (eg Growl/toast) rather than an error.
Default, Doop and Noop events
If the domainEvent() element is not explicitly specified (is left as its default value, PropertyDomainEvent.Default
), then the framework will, by default, post an event.
If this is not required, then the causeway.applib.annotation.property.domain-event.post-for-default configuration property can be set to "false"; this will disable posting.
On the other hand, if the domainEvent
has been explicitly specified to some subclass, then an event will be posted.
The framework provides PropertyDomainEvent.Doop
as such a subclass, so setting the domainEvent
attribute to this class will ensure that the event to be posted, irrespective of the configuration property setting.
And, conversely, the framework also provides PropertyDomainEvent.Noop
; if domainEvent
attribute is set to this class, then no event will be posted.
Raising events programmatically
Normally events are only raised for interactions through the UI. However, events can be raised programmatically either by calling the EventBusService API directly, or by emulating the UI by wrapping the target object using the WrapperFactory domain service.
Execution Publishing
The executionPublishing() element determines whether and how a property edit is published via the registered implementation of ExecutionSubscriber.
A common use case is to notify external "downstream" systems of changes in the state of the Apache Causeway application.
The causeway.applib.annotation.property.execution-publishing configuration property is used to determine the whether the property edits are published:
-
all
all property edits are published
-
none
no property edits are published
If there is no configuration property in application.properties
then publishing is automatically enabled.
This default can be overridden on an property-by-property basis; if executionPublishing()
is set to ENABLED
then the property edit is published irrespective of the configured value; if set to DISABLED
then the property edit is not published, again irrespective of the configured value.
For example:
import lombok.Getter;
import lombok.Setter;
public class Order {
@Property(executionPublishing=Publishing.ENABLED) (1)
@Getter @Setter
private int quantity;
// ...
}
1 | because set to enabled, will be published irrespective of the configured value. |
Command Processing
Every property edit (and action invocation for that matter) is normally reified into a concrete Command object, basically a wrapper around the XML invocation Command schema that also captures some timing metrics about the execution as well as the outcome.
The main uses cases are:
-
as a means to allow asynchronous child commands to be executed, using the WrapperFactory service;
-
as a means to audit (persist) commands, by implementing the CommandSubscriber SPI.
The Command Log extension does provide such an implementation.
Another option to achieve this is to use the ExecutionSubscriber SPI.
The commandPublishing() element can be used to explicitly enable or disable command publishing for the property edit.
CommandDtoProcessor implementations
The commandDtoProcessor() element allows an implementation of CommandDtoProcessor
to be specified.
This interface has the following API:
public interface CommandDtoProcessor {
CommandDto process( (1)
CommandDto dto); (2)
}
1 | The returned CommandDto .
This will typically be the CommandDto passed in, but may be supplemented in some way. |
2 | The CommandDto obtained already from the Command. |
This interface is used by the framework-provided implementations of ContentMappingService for the REST API, allowing Commands implementations that also implement CommandWithDto
to be further customised as they are serialized out.
The primary use case for this capability is in support of primary/secondary replication.
-
on the primary, Commands are serialized to XML. This includes the identity of the target object and the argument values of all parameters.
Any
Blob
s andClob
s are deliberately excluded from this XML (they are instead stored as references). This is to prevent the storage requirements for Command from becoming excessive. ACommandDtoProcessor
can be provided to re-attach blob information if required. -
replaying Commands requires this missing parameter information to be reinstated. The
CommandDtoProcessor
therefore offers a hook to dynamically re-attach the missingBlob
orClob
argument.
As a special case, returning null
means that the command’s DTO is effectively excluded when retrieving the list of commands.
If replicating from master to slave, this effectively allows certain commands to be ignored.
The CommandDtoProcessor.Null
class provides a convenience implementation for this requirement.
If |
Example
For an example, see Action#command().
Regular expressions
There are three elements related to enforcing regular expressions:
-
The regexPattern() element validates the contents of any string property with respect to a regular expression pattern. It is ignored if applied to properties of any other type.
-
The regexPatternFlags() element specifies flags that modify the handling of the pattern. The values are those that would normally be passed to
java.util.regex.Pattern#compile(String,int)
. -
The regexPatternReplacement() attribute specifies the error message to show if the provided argument does not match the regex pattern.
For example:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@Property(
regexPattern = "(\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+",
regexPatternFlags=Pattern.CASE_INSENSITIVE,
regexPatternReplacement =
"Must be valid email address (containing a '@') symbol" (1)
)
@Getter @Setter
private String email;
}
1 | Note that there is currently no i18n support for this phrase. |
See also
This attribute can also be specified for parameters.
Snapshotting state
The snapshot() element indicates whether the property should be included/excluded from any snapshots generated by the XmlSnapshotService.
For example:
import lombok.Getter;
import lombok.Setter;
public class Order {
@Property(snapshot=EXCLUDED)
@Getter @Setter
private Order previousOrder;
// ...
}
If the property is derived, then providing only a "getter" will also work:
public class Order {
public Order getPreviousOrder() {...}
...
}
Uploading Blobs and Clobs
The fileAccept() element applies only to Blob or Clob parameters, indicating the type of file to accept when uploading a new value. The attribute is also supported on parameters.
For example:
import lombok.Getter;
import lombok.Setter;
public class ScannedDocument {
@Property(fileAccept="image/*") (1)
@Getter @Setter
private Blob scannedImage;
}
1 | as per reference docs, either a media type (such as image/* ) or a file type extension (such as .png ). |
Hiding properties
Properties can be hidden at the domain-level, indicating that they are not visible to the end-user.
It is also possible to use @Property#hidden() to hide an action at the domain layer. |
For example:
import lombok.Getter;
import lombok.Setter;
public class Customer {
@Property(hidden=Where.EVERYWHERE)
@Getter @Setter
private int internalId;
// ...
}
The acceptable values for the where
parameter are:
-
Where.EVERYWHERE
orWhere.ANYWHERE
The property should be hidden everywhere.
-
Where.ANYWHERE
Synonym for everywhere.
-
Where.OBJECT_FORMS
The property should be hidden when displayed within an object form.
-
Where.PARENTED_TABLES
The property should be hidden when displayed as a column of a table within a parent object’s collection.
-
Where.STANDALONE_TABLES
The property should be hidden when displayed as a column of a table showing a standalone list of objects, for example as returned by a repository query.
-
Where.ALL_TABLES
The property should be hidden when displayed as a column of a table, either an object’s * collection or a standalone list. This combines
PARENTED_TABLES
andSTANDALONE_TABLES
. -
Where.NOWHERE
The property should not be hidden, overriding any other metadata/conventions that would normally cause the property to be hidden.
For example, if a property is annotated with @Title, then normally this should be hidden from all tables.
Annotating with @Property(where=Where.NOWHERE)
overrides this.
The RestfulObjects viewer has only partial support for these |