### Create a Constraint

Constraints are defined in Constraint.

If you want to reproduce what’s explained in this tutorial, remember to depend on the Core Bootstrap artifact:

Table 9. Artifact

Group ID | Artifact ID | Version
--- | --- | ---
org.qi4j.core | org.qi4j.core.bootstrap | 2.1

At runtime you will need the Core Runtime artifact too. See the Depend on Zest™ in your build tutorial for details.

#### Method Constraint

Method Constraints are declared with annotations on the method argument. The annotation itself is custom, and it is possible to make your own.

    public interface Dialer
    {
        void callPhoneNumber(@PhoneNumber String phoneNo);

    }

In the code above we say that we want the argument to the callPhoneNumber() method to be a valid phone number. This annotation is not built-in, so we need to declare it.

    @ConstraintDeclaration
    @Retention( RetentionPolicy.RUNTIME )
    @Target( { ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.METHOD } )
    public @interface PhoneNumber
    {
    }

We then need to provide the Constraint implementation.

    public class PhoneNumberConstraint
            implements Constraint<PhoneNumber, String>
    {
        public boolean isValid( PhoneNumber annotation, String number )
        {
            boolean validPhoneNumber = true; // check phone number format...
            return validPhoneNumber;  // return true if valid phone number.
        }
    }

We also need to include the Constraint on the Composites we want to have them present.

    @Constraints( PhoneNumberConstraint.class )
    public interface DialerComposite extends ServiceComposite, Dialer
    {
    }

If a Constraint is violated, then a ConstraintViolationException is thrown. The Exception contains ALL violations found in the method invocation. Concerns can be used to catch and report these violations.

    public class ParameterViolationConcern extends ConcernOf<InvocationHandler>
        implements InvocationHandler
    {
        public Object invoke( Object proxy, Method method, Object[] args )
            throws Throwable
        {
            try
            {
                return next.invoke( proxy, method, args );
            }
            catch( ConstraintViolationException e )
            {
                for( ConstraintViolation violation : e.constraintViolations() )
                {
                    String name = violation.name();
                    Object value = violation.value();
                    Annotation constraint = violation.constraint();
                    report( name, value, constraint );
                }
                throw new IllegalArgumentException("Invalid argument(s)", e);
            }
        }

        [...snip...]

        private void report( String name, Object value, Annotation constraint )
        {
        }
    }

#### Property Constraint

Property Constraints are declared on the Property method.

    public interface HasPhoneNumber
    {
        @PhoneNumber
        Property<String> phoneNumber();
    }

In this case, the Constraint associated with the phoneNumber() method, will be called before the set() method on that Property is called. If there is a constraint violation, the Exception thrown will be part of the caller, and not the composite containing the Property, so a reporting constraint on the containing Composite will not see it. If you want the containing Composite to handle the Constraint Violation, then you need to add a Concern on the Property itself, which can be done like this;

    public abstract class PhoneNumberParameterViolationConcern extends ConcernOf<HasPhoneNumber>
        implements HasPhoneNumber
    {
        @Concerns( CheckViolation.class )
        public abstract Property<String> phoneNumber();

        private abstract class CheckViolation extends ConcernOf<Property<String>>
            implements Property<String>
        {
            public void set( String number )
            {
                try
                {
                    next.set( number );
                }
                catch( ConstraintViolationException e )
                {
                    Collection<ConstraintViolation> violations = e.constraintViolations();
                    report( violations );
                }
            }

            [...snip...]

            private void report( Collection<ConstraintViolation> violations )
            {
            }
        }
    }