View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.tutorial.property.constraints;
17  
18  import org.junit.Before;
19  import org.junit.Test;
20  
21  import de.smartics.projectdoc.annotations.DocCategory;
22  import de.smartics.projectdoc.annotations.Document;
23  import de.smartics.projectdoc.annotations.topic.DocChapter;
24  import de.smartics.projectdoc.annotations.topic.DocSection;
25  import de.smartics.properties.api.config.domain.ConfigurationValidationException;
26  import de.smartics.properties.api.core.domain.PropertyValidationException;
27  import de.smartics.properties.impl.config.classpath.ClasspathConfigurationProperties;
28  import de.smartics.properties.impl.config.classpath.ClasspathConfigurationPropertiesFactory;
29  
30  /**
31   * This tutorial introduces how to add constraints to the property declaration.
32   * <p>
33   * This feature takes the burden of validation from the developers shoulders. It
34   * is based on <a href="http://jcp.org/en/jsr/detail?id=303">Beans Validation
35   * (JSR-303)</a>, so any constraint defined with this technology can be used for
36   * validating properties.
37   * </p>
38   */
39  @Document(title = "Property Constraints", sortKey = "basics0050")
40  @DocCategory({ "basics" })
41  // @DocTopic(path="basics", step="50")
42  public class PropertyConstraintsTutorial
43  {
44    private ClasspathConfigurationProperties config; // NOPMD
45  
46    private ConstraintsProperties properties;
47  
48    @Before
49    public void setUp()
50    {
51      config = createConfiguration();
52      properties = config.getProperties(ConstraintsProperties.class);
53    }
54  
55    private static ClasspathConfigurationProperties createConfiguration()
56    {
57      final ClasspathConfigurationPropertiesFactory factory =
58          new ClasspathConfigurationPropertiesFactory();
59      final ClasspathConfigurationProperties config = factory.create();
60      config.addClassPathProperties(ConstraintsProperties.class);
61      return config;
62    }
63  
64    /**
65     * <p>
66     * To check is a configuration is valid, the
67     * {@link de.smartics.properties.api.config.domain.ConfigurationProperties#validate()}
68     * has to be called.
69     * </p>
70     * {@insertCode}
71     */
72    @Test
73    @DocSection
74    public void validateMethod()
75    {
76      config.validate();
77    }
78  
79    /**
80     * <p>
81     * Per default all properties are optional. To mark a property as required use
82     * either {@link javax.validation.constraints.NotNull NotNull} or
83     * {@link org.hibernate.validator.constraints.NotBlank NotBlank}.
84     * </p>
85     * {@insertCode source="ConstraintsProperties#host()"}
86     * <p/>
87     * {@insertCode source="ConstraintsProperties#server()"}
88     */
89    @Test(expected = ConfigurationValidationException.class)
90    @DocChapter
91    public void mandatoryAndOptionalProperties()
92    {
93      config.setProperty(properties.hostPropertyKey(), " ");
94      config.setProperty(properties.serverPropertyKey(), null);
95      config.validate();
96    }
97  
98    /**
99     * <p>
100    * To specify a a property with a value from a range, use
101    * {@link de.smartics.properties.api.core.annotations.PropertyIntValueRange}.
102    * </p>
103    * {@insertCode source="ConstraintsProperties#storyPoint()"}
104    */
105   @Test
106   @DocChapter
107   public void propertyWithARangeValue()
108   {
109     config.setProperty(properties.storyPointPropertyKey(), "3");
110     config.validate();
111   }
112 
113   /**
114    * <p>
115    * The following examples shows that setting the property to an invalid value
116    * throws an exception on validation.
117    * </p>
118    * {@insertCode}
119    */
120   @Test(expected = ConfigurationValidationException.class)
121   @DocChapter
122   public void invalidRangedValueProperty()
123   {
124     config.setProperty(properties.storyPointPropertyKey(), "9999");
125     config.validate();
126   }
127 
128   /**
129    * <p>
130    * To specify a a property with a value from an enumeration, use an enum
131    * return type.
132    * </p>
133    * {@insertCode source="ConstraintsProperties#priority()"}
134    */
135   @Test
136   @DocChapter
137   public void propertyWithAEnumValue()
138   {
139     config.setProperty(properties.priorityPropertyKey(), "required");
140     config.validate();
141   }
142 
143   /**
144    * <p>
145    * The following examples shows that setting the property to an invalid value
146    * throws an exception on validation.
147    * </p>
148    * {@insertCode}
149    */
150   @Test(expected = ConfigurationValidationException.class)
151   @DocChapter
152   public void invalidEnumValuedProperty()
153   {
154     config.setProperty(properties.priorityPropertyKey(), "##unknown##");
155     config.validate();
156   }
157 
158   /**
159    * <p>
160    * Any property value - valid or not - may be added at any time.
161    * </p>
162    * {@insertCode source="ConstraintsProperties#host()"}
163    */
164   @Test
165   @DocSection
166   public void noValidationAtAppend()
167   {
168     config.setProperty(properties.hostPropertyKey(), " ");
169   }
170 
171   /**
172    * <p>
173    * But as soon as it is accessed, it is guaranteed to be validated.
174    * </p>
175    */
176   @Test(expected = PropertyValidationException.class)
177   @DocSection
178   public void validationOnAccess()
179   {
180     config.setProperty(properties.hostPropertyKey(), " ");
181     properties.host();
182   }
183 
184 }