001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.server.validation; 018 019import org.apache.juneau.marshall.*; 020 021/** 022 * Wire-friendly snapshot of a single Jakarta Bean Validation constraint violation, suitable for inclusion in an 023 * HTTP error response body. 024 * 025 * <p> 026 * Produced by {@link BeanValidator} from a {@code jakarta.validation.ConstraintViolation}, with deliberately 027 * narrow surface so the bean is decoupled from the optional {@code jakarta.validation} runtime dependency. The 028 * {@link #invalidValue} field is omitted by default to avoid echoing potentially sensitive request data back to 029 * the client; callers can opt back in via {@link #setInvalidValue(String)}. 030 * 031 * <h5 class='section'>JSON shape:</h5> 032 * <p class='bjson'> 033 * { 034 * <jok>"path"</jok>: <jov>"name"</jov>, 035 * <jok>"message"</jok>: <jov>"must not be blank"</jov>, 036 * <jok>"constraint"</jok>: <jov>"NotBlank"</jov> 037 * } 038 * </p> 039 * 040 * <h5 class='section'>See Also:</h5><ul> 041 * <li class='jc'>{@link ValidationException} 042 * <li class='jc'>{@link BeanValidator} 043 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerValidation">Jakarta Bean Validation</a> 044 * </ul> 045 * 046 * @since 10.0.0 047 */ 048@Marshalled 049public class ValidationViolation { 050 051 private String path; 052 private String message; 053 private String constraint; 054 private String invalidValue; 055 056 /** 057 * Default constructor. 058 */ 059 public ValidationViolation() {} 060 061 /** 062 * Convenience constructor populating the three non-sensitive fields. 063 * 064 * @param path The property path string (e.g. {@code "name"} or {@code "items[2].sku"}). May be <jk>null</jk>. 065 * @param message The localized violation message produced by the constraint validator. May be <jk>null</jk>. 066 * @param constraint The simple name of the constraint annotation (e.g. {@code "NotBlank"}). May be <jk>null</jk>. 067 */ 068 public ValidationViolation(String path, String message, String constraint) { 069 this.path = path; 070 this.message = message; 071 this.constraint = constraint; 072 } 073 074 /** 075 * The Jakarta-Validation property path string — the dotted/indexed path from the validated root bean 076 * down to the violating field (e.g. {@code "name"} or {@code "items[2].sku"}). 077 * 078 * @return The property path, or <jk>null</jk> if not set. 079 */ 080 public String getPath() { return path; } 081 082 /** 083 * Sets the property path. 084 * 085 * @param value The new value. Can be <jk>null</jk> to unset the property. 086 * @return This object. 087 */ 088 public ValidationViolation setPath(String value) { 089 path = value; 090 return this; 091 } 092 093 /** 094 * The localized violation message from the constraint validator (e.g. {@code "must not be blank"}). 095 * 096 * @return The message, or <jk>null</jk> if not set. 097 */ 098 public String getMessage() { return message; } 099 100 /** 101 * Sets the message. 102 * 103 * @param value The new value. Can be <jk>null</jk> to unset the property. 104 * @return This object. 105 */ 106 public ValidationViolation setMessage(String value) { 107 message = value; 108 return this; 109 } 110 111 /** 112 * The simple name of the constraint annotation that was violated (e.g. {@code "NotBlank"}, {@code "Size"}). 113 * 114 * @return The constraint name, or <jk>null</jk> if not set. 115 */ 116 public String getConstraint() { return constraint; } 117 118 /** 119 * Sets the constraint. 120 * 121 * @param value The new value. Can be <jk>null</jk> to unset the property. 122 * @return This object. 123 */ 124 public ValidationViolation setConstraint(String value) { 125 constraint = value; 126 return this; 127 } 128 129 /** 130 * The (string-rendered) invalid value that triggered the violation. 131 * 132 * <p> 133 * Omitted by default to avoid echoing potentially sensitive request data back to the client; populated only 134 * when the caller explicitly opts in via {@link #setInvalidValue(String)} (typically from a 135 * {@code BeanValidator} configured with {@code includeInvalidValue(true)}). 136 * 137 * @return The invalid value, or <jk>null</jk> if not set. 138 */ 139 public String getInvalidValue() { return invalidValue; } 140 141 /** 142 * Sets the invalid value. 143 * 144 * @param value The new value. Can be <jk>null</jk> to unset the property. 145 * @return This object. 146 */ 147 public ValidationViolation setInvalidValue(String value) { 148 invalidValue = value; 149 return this; 150 } 151}