<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> 
        <base href="https://hibernate.atlassian.net"> 
        <title>Message Title</title> 
    </head> 
    <body class="jira" style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 1.429"> 
        <table id="background-table" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f5f5f5; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt" bgcolor="#f5f5f5"> 
            <!-- header here --> 
            <tbody>
                <tr> 
                    <td id="header-pattern-container" style="padding: 0px; border-collapse: collapse; padding: 10px 20px"> 
                        <table id="header-pattern" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                            <tbody>
                                <tr> 
                                    <td id="header-avatar-image-container" valign="top" style="padding: 0px; border-collapse: collapse; vertical-align: top; width: 32px; padding-right: 8px" width="32"> <img id="header-avatar-image" class="image_fix" src="cid:jira-generated-image-avatar-2c677174-1c15-4470-a81a-871cf7195442" height="32" width="32" border="0" style="border-radius: 3px; vertical-align: top"> </td> 
                                    <td id="header-text-container" valign="middle" style="padding: 0px; border-collapse: collapse; vertical-align: middle; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> <a class="user-hover" rel="rtedin" id="email_rtedin" href="https://hibernate.atlassian.net/secure/ViewProfile.jspa?name=rtedin" style="color:#6c797f;; color: #3b73af; text-decoration: none">Rafael Tedin Alvarez</a> <strong>commented</strong> on <a href="https://hibernate.atlassian.net/browse/HV-1013" style="color: #3b73af; text-decoration: none"><img src="cid:jira-generated-image-avatar-5a9048ed-8ca7-4f8b-b73f-ba30c3dee0eb" height="16" width="16" border="0" align="absmiddle" alt="Bug"> HV-1013</a> </td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
                <tr> 
                    <td id="email-content-container" style="padding: 0px; border-collapse: collapse; padding: 0 20px"> 
                        <table id="email-content-table" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-spacing: 0; border-collapse: separate"> 
                            <tbody>
                                <tr> 
                                    <!-- there needs to be content in the cell for it to render in some clients --> 
                                    <td class="email-content-rounded-top mobile-expand" style="padding: 0px; border-collapse: collapse; color: #ffffff; padding: 0 15px 0 16px; height: 15px; background-color: #ffffff; border-left: 1px solid #cccccc; border-top: 1px solid #cccccc; border-right: 1px solid #cccccc; border-bottom: 0; border-top-right-radius: 5px; border-top-left-radius: 5px; height: 10px; line-height: 10px; padding: 0 15px 0 16px; mso-line-height-rule: exactly" height="10" bgcolor="#ffffff">&nbsp;</td> 
                                </tr> 
                                <tr> 
                                    <td class="email-content-main mobile-expand " style="padding: 0px; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff" bgcolor="#ffffff"> 
                                        <table class="page-title-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                            <tbody>
                                                <tr> 
                                                    <td style="vertical-align: top;; padding: 0px; border-collapse: collapse; padding-right: 5px; font-size: 20px; line-height: 30px; mso-line-height-rule: exactly" class="page-title-pattern-header-container"> <span class="page-title-pattern-header" style="font-family: Arial, sans-serif; padding: 0; font-size: 20px; line-height: 30px; mso-text-raise: 2px; mso-line-height-rule: exactly; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HV-1013" style="color: #3b73af; text-decoration: none">Re: Validator invokes hashCode() with null mandatory field </a> </span> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <tr> 
                                    <td id="text-paragraph-pattern-top" class="email-content-main mobile-expand  comment-top-pattern" style="padding: 0px; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff; border-bottom: none; padding-bottom: 0" bgcolor="#ffffff"> 
                                        <table class="text-paragraph-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
                                            <tbody>
                                                <tr> 
                                                    <td class="text-paragraph-pattern-container mobile-resize-text " style="padding: 0px; border-collapse: collapse; padding: 0 0 10px 0"> <p style="margin: 10px 0 0 0; margin-top: 0">Thanks for the quick reply!</p> <p style="margin: 10px 0 0 0">What I wanted to say is that the validation relies on the <tt>hashCode()</tt> and <tt>hashCode()</tt> (at least in our use case) only works if the instance is already valid. So in the use case I mentioned the validation only works if the instance is already valid, defeating the purpose of validation.</p> <p style="margin: 10px 0 0 0">JSON deserialization is working fine. When we receive a JSON string, we can create an instance of our immutable class without problems. The thing is that the deserialized instance may not follow the class invariant (since it was not created through the builder that would ensure it). Then we need validation to ensure that the deserialized instance follows indeed the class invariant (or preconditions/assumptions if you prefer).</p> <p style="margin: 10px 0 0 0">Take the following (made up) example where <tt>Son</tt> is our automatically generated immutable class and <tt>SonBuilder</tt> the automatically generated builder. We cannot (for the most part) change their code.</p> 
                                                        <div class="code panel" style="border-width: 1px;; border: 1px solid #cccccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #cccccc; -moz-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; margin: 9px 0">
                                                            <div class="codeContent panelContent" style="padding: 9px 12px"> 
                                                                <pre class="code-java" style="margin: 10px 0 0 0; margin-top: 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal">
<span class="code-keyword" style="color: #000091">public</span> <span class="code-keyword" style="color: #000091">final</span> class Son {
    @NotNull
    <span class="code-keyword" style="color: #000091">private</span> Father father;

    <span class="code-keyword" style="color: #000091">public</span> Father getFather() {
        <span class="code-keyword" style="color: #000091">return</span> father;
    }

    @Override
    <span class="code-keyword" style="color: #000091">public</span> <span class="code-object" style="color: #910091">int</span> hashCode() {
        <span class="code-object" style="color: #910091">int</span> h = 31;
        <span class="code-keyword" style="color: #000091">return</span> h * father.hashCode(); <span class="code-comment" style="color: #808080">// May <span class="code-keyword" style="color: #000091; color: #808080">throw</span> NullPointerException <span class="code-keyword" style="color: #000091; color: #808080">if</span> class invariant is violated.
</span>    }

    @Override
    <span class="code-keyword" style="color: #000091">public</span> <span class="code-object" style="color: #910091">boolean</span> equals(<span class="code-object" style="color: #910091">Object</span> o) {
        <span class="code-comment" style="color: #808080">// ...
</span>    }
}

<span class="code-keyword" style="color: #000091">public</span> <span class="code-keyword" style="color: #000091">final</span> class SonBuilder {

    <span class="code-comment" style="color: #808080">// ...
</span>    <span class="code-comment" style="color: #808080">// Methods <span class="code-keyword" style="color: #000091; color: #808080">for</span> setting a father and other helper methods.
</span>    <span class="code-comment" style="color: #808080">// ...
</span>
    <span class="code-keyword" style="color: #000091">public</span> Son build() {
        Son son = <span class="code-keyword" style="color: #000091">new</span> Son();
        <span class="code-comment" style="color: #808080">// Set fields of son ...
</span>        checkInvariant(son); <span class="code-comment" style="color: #808080">// Ensures the class invariant (i.e. father != <span class="code-keyword" style="color: #000091; color: #808080">null</span>).
</span>        <span class="code-keyword" style="color: #000091">return</span> son;
    }
}
</pre> 
                                                            </div>
                                                        </div> <p style="margin: 10px 0 0 0">If we use the builder, we can be sure that the resulting <tt>Son</tt> instance is valid. However if someone sends a JSON (e.g. as part of a web service request), the deserialized instance may be invalid since deserialization does not use the builder. If the JSON does not contain <tt>father</tt>, the instance is deserialized just fine, but the field <tt>father</tt> is set to <tt>null</tt>. Nevertheless the web service has to ensure that it is dealing with correct instances. Hence at this point we need the additional bean validation. But since the field is <tt>null</tt> <tt>hashCode()</tt> will throw and we cannot properly validate the instance.</p> <p style="margin: 10px 0 0 0">Changing the <tt>hashCode()</tt> to circumvent the class invariant might be possible in some cases, but not in others. We think it's a not so good idea in our use case, since this could mask problems and errors in our automatically generated builders. In other words we like that <tt>hashCode()</tt> fails if the instance does not follow its invariant as this gives us the opportunity to discover errors.</p> <p style="margin: 10px 0 0 0">I think that the behavior of the validation is currently conceptually wrong because it requires immunity to invalid inner state from some methods (from <tt>hashCode()</tt> at least). But it's because of invalid inner state that we use validation: to be sure that we can safely use all the methods of the class.</p> <p style="margin: 10px 0 0 0">I hope I succeeded to clarify the context a bit more and thanks again!</p> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <tr> 
                                    <td class="email-content-main mobile-expand " style="padding: 0px; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff" bgcolor="#ffffff"> 
                                        <table id="actions-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> 
                                            <tbody>
                                                <tr> 
                                                    <td id="actions-pattern-container" valign="middle" style="padding: 0px; border-collapse: collapse; padding: 10px 0 10px 24px; vertical-align: middle; padding-left: 0"> 
                                                        <table align="left" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                                            <tbody>
                                                                <tr> 
                                                                    <td class="actions-pattern-action-icon-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0px; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HV-1013#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none"> <img class="actions-pattern-action-icon-image" src="cid:jira-generated-image-static-comment-icon-f058af2c-0718-4ee9-882f-552cecb1f033" alt="Add Comment" title="Add Comment" height="16" width="16" border="0" style="vertical-align: middle"> </a> </td> 
                                                                    <td class="actions-pattern-action-text-container" style="padding: 0px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px"> <a href="https://hibernate.atlassian.net/browse/HV-1013#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none">Add Comment</a> </td> 
                                                                </tr> 
                                                            </tbody>
                                                        </table> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <!-- there needs to be content in the cell for it to render in some clients --> 
                                <tr> 
                                    <td class="email-content-rounded-bottom mobile-expand" style="padding: 0px; border-collapse: collapse; color: #ffffff; padding: 0 15px 0 16px; height: 5px; line-height: 5px; background-color: #ffffff; border-top: 0; border-left: 1px solid #cccccc; border-bottom: 1px solid #cccccc; border-right: 1px solid #cccccc; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; mso-line-height-rule: exactly" height="5" bgcolor="#ffffff">&nbsp;</td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
                <tr> 
                    <td id="footer-pattern" style="padding: 0px; border-collapse: collapse; padding: 12px 20px"> 
                        <table id="footer-pattern-container" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                            <tbody>
                                <tr> 
                                    <td id="footer-pattern-text" class="mobile-resize-text" width="100%" style="padding: 0px; border-collapse: collapse; color: #999999; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px"> This message was sent by Atlassian JIRA <span id="footer-build-information">(v7.2.0-OD-03-014#72000-<span title="1e7aa97762d55bf4dca03ec836996749f75d8b3e" data-commit-id="1e7aa97762d55bf4dca03ec836996749f75d8b3e}">sha1:1e7aa97</span>)</span> </td> 
                                    <td id="footer-pattern-logo-desktop-container" valign="top" style="padding: 0px; border-collapse: collapse; padding-left: 20px; vertical-align: top"> 
                                        <table style="border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt"> 
                                            <tbody>
                                                <tr> 
                                                    <td id="footer-pattern-logo-desktop-padding" style="padding: 0px; border-collapse: collapse; padding-top: 3px"> <img id="footer-pattern-logo-desktop" src="cid:jira-generated-image-static-footer-desktop-logo-97394cf1-9d15-492b-bd01-6703299b5017" alt="Atlassian logo" title="Atlassian logo" width="169" height="36" class="image_fix"> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
            </tbody>
        </table>   
    </body>
</html>