{"componentChunkName":"component---node-modules-gatsby-theme-medium-to-own-blog-src-templates-blog-post-js","path":"/controllers-and-validation-with-waffle/","result":{"data":{"site":{"siteMetadata":{"siteUrl":"https://javame.netlify.app","githubUrl":"https://github.com/aterreno/blog"}},"mdx":{"fields":{"slug":"/controllers-and-validation-with-waffle/"},"excerpt":"One of the nicest features of  Waffle  are the  Validators .  In order to have server side validation on some controller logic you don’t…","timeToRead":1,"frontmatter":{"title":"Controllers and validation with Waffle","description":"","categories":[],"date":"November 20, 2008","canonical_link":"https://javame.netlify.app//controllers-and-validation-with-waffle-43c667a47d11"},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Controllers and validation with Waffle\",\n  \"description\": \"\",\n  \"date\": \"2008-11-20T00:00:00.000Z\",\n  \"categories\": [],\n  \"published\": true,\n  \"canonical_link\": \"https://javame.netlify.app//controllers-and-validation-with-waffle-43c667a47d11\",\n  \"redirect_from\": [\"/controllers-and-validation-with-waffle-43c667a47d11\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"One of the nicest features of \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://waffle.codehaus.org/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Waffle\"), \" are the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://waffle.codehaus.org/validation.html\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Validators\"), \".\\xA0\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"In order to have server side validation on some controller logic you don\\u2019t need to extend or write any fluff.\\xA0\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"Given a method on your controller like this one:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"package waffle.controllers;\\n\\nimport org.codehaus.waffle.view.RedirectView;\\nimport org.codehaus.waffle.view.View;\\n\\npublic class UserLoginController {\\n\\npublic View login(String username, String password) {\\n            return new RedirectView(&quot;homepage.waffle&quot;);\\n    }\\n\\n}\\n\")), mdx(\"p\", null, \"All you have to do is write a class named UserLoginControllerValidator (just for convention, not strictly necessary) and a method with the same syntax as the action on the Controller with also the ErrorsContext parameter in the signature.\"), mdx(\"p\", null, \"For a simple application login it will look more or less like this:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"package waffle.validators;\\n\\nimport org.codehaus.waffle.validation.ErrorsContext;\\nimport org.codehaus.waffle.validation.FieldErrorMessage;\\n\\nimport waffle.services.AuthenticationExeption;\\nimport waffle.services.AuthenticationService;\\n\\npublic class UserLoginControllerValidator {\\n\\nprivate final AuthenticationService authenticationService;\\n\\npublic UserLoginControllerValidator(AuthenticationService authenticationService) {\\n                this.authenticationService = authenticationService;\\n        }\\n\\npublic void login(ErrorsContext errors, String username, String password) {\\n                try {\\n                        authenticationService.login(username, password);\\n                } catch (AuthenticationExeption exeption) {\\n                        errors.addErrorMessage(new FieldErrorMessage(\\\"name\\\", username, exeption.getMessage()));\\n                }\\n        }\\n}\\n\")), mdx(\"p\", null, \"Well the design is pretty clean right?\\xA0\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"There\\u2019s no coupling, there is no inheritance involved and the responsibilities of the classes are well isolated: the controller controls, redirects, the validator validates.\"), mdx(\"p\", null, \"With such an easy design also testing becomes easier.\\xA0\", mdx(\"br\", {\n    parentName: \"p\"\n  }), \"\\n\", \"Here a sample test to check that the proper message has been added to the ErrorContext.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"package waffle.controllers;\\n\\nimport static org.mockito.Matchers.argThat;\\nimport static org.mockito.Mockito.doThrow;\\nimport static org.mockito.Mockito.mock;\\nimport static org.mockito.Mockito.verify;\\n\\nimport org.codehaus.waffle.validation.ErrorsContext;\\nimport org.codehaus.waffle.validation.FieldErrorMessage;\\nimport org.junit.Test;\\n\\nimport waffle.services.AuthenticationExeption;\\nimport waffle.services.AuthenticationService;\\nimport waffle.validators.UserLoginControllerValidator;\\n\\npublic class UserLoginControllerValidatorTest {\\n\\nprivate static final String username = \\\"test\\\";\\n        private static final String password = \\\"test\\\";\\n\\n@Test\\n        public void shouldAddAnUserNotFoundErrorWhenUserNotFoundWithTheService() throws Exception {\\n                // given\\n                AuthenticationService service = mock(AuthenticationService.class);\\n                UserLoginControllerValidator validator = new UserLoginControllerValidator(service);\\n                ErrorsContext errors = mock(ErrorsContext.class);\\n\\n// when\\n                doThrow(new AuthenticationExeption(\\\"User not found\\\")).when(service).login(username, password);\\n                validator.login(errors, username, password);\\n\\n// then\\n                FieldErrorMessage expectedErrorMessage = new FieldErrorMessage(\\\"name\\\", username, \\\"User not found\\\");\\n                verify(errors).addErrorMessage(argThat(new IsAnErrorMessageLike(expectedErrorMessage)));\\n        }\\n\\n}\\n\")), mdx(\"p\", null, \"I\\u2019m, indeed, using \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://code.google.com/p/mockito/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Mockito\"), \" and IsAnErrorMessageLike is a custom \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"http://code.google.com/p/hamcrest/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Hamcrest Matcher\"), \", it looks like:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"package waffle.controllers;\\n\\nimport org.codehaus.waffle.validation.ErrorMessage;\\nimport org.codehaus.waffle.validation.FieldErrorMessage;\\nimport org.hamcrest.BaseMatcher;\\nimport org.hamcrest.Description;\\n\\npublic class IsAnErrorMessageLike extends BaseMatcher {\\n\\nprivate final FieldErrorMessage fieldErrorMessage;\\n\\npublic IsAnErrorMessageLike(FieldErrorMessage fieldErrorMessage) {\\n            this.fieldErrorMessage = fieldErrorMessage;\\n    }\\n\\n@Override\\n    public boolean matches(Object object) {\\n            if (object == null)\\n                    return false;\\n            if (!(object instanceof FieldErrorMessage))\\n                    return false;\\n\\nFieldErrorMessage other = (FieldErrorMessage) object;\\n\\nif (other.getMessage().equals(fieldErrorMessage.getMessage())\\n                            &amp;&amp; (other.getName().equals(fieldErrorMessage.getName()))\\n                            &amp;&amp; (other.getType().equals(fieldErrorMessage.getType()))\\n                            &amp;&amp; (other.getMessage().equals(fieldErrorMessage.getMessage()))                                \\n                            &amp;&amp; (other.getValue().equals(fieldErrorMessage.getValue())))\\n                    return true;\\n\\nreturn false;\\n    }\\n\\n@Override\\n    public void describeTo(Description description) {\\n            description.appendText(fieldErrorMessage.toString());\\n    }\\n\\n}\\n\")));\n}\n;\nMDXContent.isMDXComponent = true;"},"allWebMentionEntry":{"nodes":[]}},"pageContext":{"id":"1b08466d-e3e9-5911-8ec9-eafac2a67e23","previous":{"id":"e9ec43dd-8bd7-5fff-8411-33e17c5e37e5","fields":{"slug":"/a-cool-guy-a-cool-software-balsamiq-application-mockups/","published":true},"frontmatter":{"redirect_from":["/a-cool-guy-a-cool-software-balsamiq-application-mockups-87afd59cbe9f"],"redirect_to":null,"title":"A cool guy, a cool software: Balsamiq application mock-ups"}},"next":{"id":"04e41901-8d78-5124-8966-55d3f433013f","fields":{"slug":"/mavenized/","published":true},"frontmatter":{"redirect_from":["/mavenized-c37562c27b22"],"redirect_to":null,"title":"Mavenized"}},"permalink":"https://javame.netlify.app/controllers-and-validation-with-waffle/","themeOptions":{"plugins":[],"config":{"title":"Antonio Terreno","description":"Antonio Terreno's blog archive","shortBio":"","bio":"Principal Consultant at Equal Experts","author":"Antonio Terreno","githubUrl":"https://github.com/aterreno/blog","siteUrl":"https://javame.netlify.app/","social":{"twitter":"javame","medium":"","facebook":"","github":"aterreno","linkedin":"antonioterreno","instagram":"tritonitri"},"goatCounterCode":null}}}},"staticQueryHashes":["4131332129","645483741"]}