Commits

Endy Muhardin committed bd2bf06

implement validasi

  • Participants
  • Parent commits 1d3259c

Comments (0)

Files changed (22)

File belajar-restful-domain/src/main/java/com/artivisi/belajar/restful/domain/ApplicationConfig.java

 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
-
 import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.validator.constraints.NotEmpty;
 
 @Entity
 @Table(name="c_application_config")
 	@GenericGenerator(name="system-uuid", strategy = "uuid2")
 	private String id;
 	
+        @NotNull
+        @NotEmpty
 	@Column(nullable=false, unique=true)
 	private String name;
+        
+        @NotNull
+        @NotEmpty
 	@Column(nullable=false)
 	private String label;
+        
+        @NotNull
+        @NotEmpty
 	@Column(nullable=false)
 	private String value;
+        
 	public String getId() {
 		return id;
 	}

File belajar-restful-domain/src/main/java/com/artivisi/belajar/restful/domain/Menu.java

 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
 import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.validator.constraints.NotEmpty;
 
 /**
  *
     @Column(name = "menu_action")
     private String action;
     
+    @NotNull
+    @NotEmpty
     @Column(name = "label", nullable = false)
     private String label;
     
+    @NotNull
+    @Min(0)
     @Column(name = "menu_level", nullable = false)
     private Integer level = 0;
     
+    @NotNull
+    @Min(0)
     @Column(name = "menu_order", nullable = false)
     private Integer order = 0;
     

File belajar-restful-domain/src/main/java/com/artivisi/belajar/restful/domain/Permission.java

 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.validator.constraints.NotEmpty;
 
 @Entity
 @Table(name = "c_security_permission")
     @GenericGenerator(name = "system-uuid", strategy = "uuid2")
     private String id;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "permission_label", nullable = false, unique = false)
     private String label;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "permission_value", nullable = false, unique = true)
     private String value;
 

File belajar-restful-domain/src/main/java/com/artivisi/belajar/restful/domain/Role.java

 import javax.persistence.ManyToMany;
 import javax.persistence.OrderBy;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.validator.constraints.NotEmpty;
 
 @Entity
 @Table(name = "c_security_role")
     @GenericGenerator(name = "system-uuid", strategy = "uuid2")
     private String id;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "name", nullable = false, unique = true)
     private String name;
 

File belajar-restful-domain/src/main/java/com/artivisi/belajar/restful/domain/User.java

 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.validator.constraints.NotEmpty;
 
 @Entity
 @Table(name = "c_security_user")
     @GenericGenerator(name = "system-uuid", strategy = "uuid2")
     private String id;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "username", nullable = false, unique = true)
     private String username;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "password", nullable = false, unique = false)
     private String password;
     
+    @NotNull
     @Column(name = "active", nullable = false, unique = false)
     private Boolean active;
 
+    @NotNull
+    @NotEmpty
     @Column(name = "fullname", nullable = false, unique = false)
     private String fullname;
 
+    @NotNull
     @ManyToOne
     @JoinColumn(name = "id_role", nullable = false)
     private Role role;

File belajar-restful-web/src/main/java/com/artivisi/belajar/restful/ui/controller/ApplicationConfigController.java

 import com.artivisi.belajar.restful.domain.ApplicationConfig;
 import com.artivisi.belajar.restful.service.BelajarRestfulService;
 import com.google.common.io.Files;
+import javax.validation.Valid;
 import org.springframework.data.domain.Pageable;
 
 @Controller
 
     @RequestMapping(value = "/config", method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public void create(@RequestBody ApplicationConfig config, HttpServletRequest request, HttpServletResponse response) {
+    public void create(@RequestBody @Valid ApplicationConfig config, HttpServletRequest request, HttpServletResponse response) {
         belajarRestfulService.save(config);
         String requestUrl = request.getRequestURL().toString();
         URI uri = new UriTemplate("{requestUrl}/{id}").expand(requestUrl, config.getId());
 
     @RequestMapping(method = RequestMethod.PUT, value = "/config/{id}")
     @ResponseStatus(HttpStatus.OK)
-    public void update(@PathVariable String id, @RequestBody ApplicationConfig config) {
+    public void update(@PathVariable String id, @RequestBody @Valid ApplicationConfig config) {
         ApplicationConfig a = belajarRestfulService.findApplicationConfigById(id);
         if (a == null) {
             logger.warn("Config dengan id [{}] tidak ditemukan", id);

File belajar-restful-web/src/main/java/com/artivisi/belajar/restful/ui/controller/MenuController.java

 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
     @RequestMapping(value = "/menu", method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public void create(@RequestBody Menu x, HttpServletRequest request, HttpServletResponse response) {
+    public void create(@RequestBody @Valid Menu x, HttpServletRequest request, HttpServletResponse response) {
         belajarRestfulService.save(x);
         String requestUrl = request.getRequestURL().toString();
         URI uri = new UriTemplate("{requestUrl}/{id}").expand(requestUrl, x.getId());
 
     @RequestMapping(method = RequestMethod.PUT, value = "/menu/{id}")
     @ResponseStatus(HttpStatus.OK)
-    public void update(@PathVariable String id, @RequestBody Menu x) {
+    public void update(@PathVariable String id, @RequestBody @Valid Menu x) {
         Menu a = belajarRestfulService.findMenuById(id);
         if (a == null) {
             logger.warn("Menu dengan id [{}] tidak ditemukan", id);

File belajar-restful-web/src/main/java/com/artivisi/belajar/restful/ui/controller/PermissionController.java

 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
     @RequestMapping(value = "/permission", method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public void create(@RequestBody Permission x, HttpServletRequest request, HttpServletResponse response) {
+    public void create(@RequestBody @Valid Permission x, HttpServletRequest request, HttpServletResponse response) {
         belajarRestfulService.save(x);
         String requestUrl = request.getRequestURL().toString();
         URI uri = new UriTemplate("{requestUrl}/{id}").expand(requestUrl, x.getId());
 
     @RequestMapping(method = RequestMethod.PUT, value = "/permission/{id}")
     @ResponseStatus(HttpStatus.OK)
-    public void update(@PathVariable String id, @RequestBody Permission x) {
+    public void update(@PathVariable String id, @RequestBody @Valid Permission x) {
         Permission a = belajarRestfulService.findPermissionById(id);
         if (a == null) {
             logger.warn("Permission dengan id [{}] tidak ditemukan", id);

File belajar-restful-web/src/main/java/com/artivisi/belajar/restful/ui/controller/RoleController.java

 import com.artivisi.belajar.restful.domain.Role;
 import com.artivisi.belajar.restful.service.BelajarRestfulService;
 import java.net.URI;
-import java.util.ArrayList;
 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
     @RequestMapping(value = "/role", method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public void create(@RequestBody Role x, HttpServletRequest request, HttpServletResponse response) {
+    public void create(@RequestBody @Valid Role x, HttpServletRequest request, HttpServletResponse response) {
         belajarRestfulService.save(x);
         String requestUrl = request.getRequestURL().toString();
         URI uri = new UriTemplate("{requestUrl}/{id}").expand(requestUrl, x.getId());
 
     @RequestMapping(method = RequestMethod.PUT, value = "/role/{id}")
     @ResponseStatus(HttpStatus.OK)
-    public void update(@PathVariable String id, @RequestBody Role x) {
+    public void update(@PathVariable String id, @RequestBody @Valid Role x) {
         Role a = belajarRestfulService.findRoleById(id);
         if (a == null) {
             logger.warn("Role dengan id [{}] tidak ditemukan", id);

File belajar-restful-web/src/main/java/com/artivisi/belajar/restful/ui/controller/UserController.java

 import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
     @RequestMapping(value = "/user", method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public void create(@RequestBody User x, HttpServletRequest request, HttpServletResponse response) {
+    public void create(@RequestBody @Valid User x, HttpServletRequest request, HttpServletResponse response) {
         belajarRestfulService.save(x);
         String requestUrl = request.getRequestURL().toString();
         URI uri = new UriTemplate("{requestUrl}/{id}").expand(requestUrl, x.getId());
 
     @RequestMapping(method = RequestMethod.PUT, value = "/user/{id}")
     @ResponseStatus(HttpStatus.OK)
-    public void update(@PathVariable String id, @RequestBody User x) {
+    public void update(@PathVariable String id, @RequestBody @Valid User x) {
         User a = belajarRestfulService.findUserById(id);
         if (a == null) {
             logger.warn("User dengan id [{}] tidak ditemukan", id);

File belajar-restful-web/src/main/webapp/js/aplikasi-controller.js

             if(x.id == null){
                 return; 
             }
-            $scope.currentConfig = ApplicationConfigService.get({
-                configId: x.id
-                });
+            $scope.currentConfig = ApplicationConfigService.get({configId: x.id}, function(data){
+                $scope.original = angular.copy(data);
+            });
         };
         $scope.baru = function(){
             $scope.currentConfig = null;
+            $scope.original = null;
         }
         $scope.simpan = function(){
             ApplicationConfigService.save($scope.currentConfig)
             .success(function(){
                 $scope.configs = ApplicationConfigService.query();
-                $scope.currentConfig = null;
+                $scope.baru();
             });
         }
         $scope.remove = function(x){
                 $scope.configs = ApplicationConfigService.query();
             });
         }
+        $scope.isClean = function(){
+            return angular.equals($scope.original, $scope.currentConfig);
+        }
     }])
     .controller('SystemMenuController', ['$scope', 'SystemMenuService', function($scope, SystemMenuService){
         $scope.menus = SystemMenuService.query();
             if(x.id == null){
                 return; 
             }
-            $scope.currentMenu = SystemMenuService.get({
-                id: x.id
+            $scope.currentMenu = SystemMenuService.get({id: x.id}, function(data){
+                $scope.original = angular.copy(data);
             });
             
             $scope.parentSelection = _.filter($scope.menus, function(m){
         };
         $scope.baru = function(){
             $scope.currentMenu = null;
+            $scope.original = null;
         }
         $scope.simpan = function(){
             SystemMenuService.save($scope.currentMenu)
             .success(function(){
                 $scope.menus = SystemMenuService.query();
-                $scope.currentMenu = null;
+                $scope.baru();
             });
         }
         $scope.remove = function(x){
                 $scope.menus = SystemMenuService.query();
             });
         }
+        $scope.isClean = function(){
+            return angular.equals($scope.original, $scope.currentMenu);
+        }
     }])
     .controller('PermissionController', ['$scope', 'PermissionService', function($scope, PermissionService){
         $scope.permissions = PermissionService.query();
             if(x.id == null){
                 return; 
             }
-            $scope.currentPermission = PermissionService.get({
-                id: x.id
-                });
+            $scope.currentPermission = PermissionService.get({id: x.id}, function(data){
+                $scope.original = angular.copy(data);
+            });
         };
         $scope.baru = function(){
             $scope.currentPermission = null;
+            $scope.original = null;
         }
         $scope.simpan = function(){
             PermissionService.save($scope.currentPermission)
             .success(function(){
                 $scope.permissions = PermissionService.query();
-                $scope.currentPermission = null;
+                $scope.baru();
             });
         }
         $scope.remove = function(x){
                 $scope.permissions = PermissionService.query();
             });
         }
+        $scope.isClean = function(){
+            return angular.equals($scope.original, $scope.currentPermission);
+        }
     }])
     .controller('RoleController', ['$scope', 'RoleService', function($scope, RoleService){
         $scope.roles = RoleService.query();
             if(x.id == null){
                 return; 
             }
-            $scope.currentRole = RoleService.get({
-                id: x.id
+            $scope.currentRole = RoleService.get({id: x.id}, function(data){
+                $scope.original = angular.copy(data);
             });
             RoleService.unselectedPermission(x).success(function(data){
                 $scope.unselectedPermission = data;
         };
         $scope.baru = function(){
             $scope.currentRole = null;
+            $scope.original = null;
         }
         $scope.simpan = function(){
             RoleService.save($scope.currentRole)
             .success(function(){
                 $scope.roles = RoleService.query();
-                $scope.currentRole = null;
+                $scope.baru();
             });
         }
         $scope.remove = function(x){
             });
         }
         
+        
+        $scope.isClean = function(){
+            return angular.equals($scope.original, $scope.currentRole);
+        }
+        
         $scope.selectAllPermission = function($event){
             if($event.target.checked){
                 for ( var i = 0; i < $scope.unselectedPermission.length; i++) {
             if(x.id == null){
                 return; 
             }
-            $scope.currentUser = UserService.get({
-                id: x.id
-                });
+            $scope.currentUser = UserService.get({id: x.id}, function(data){
+                $scope.original = angular.copy(data);
+            });
         };
         $scope.baru = function(){
             $scope.currentUser = null;
+            $scope.original = null;
         }
         $scope.simpan = function(){
             if($scope.currentUser.active == null){
             UserService.save($scope.currentUser)
             .success(function(){
                 $scope.users = UserService.query();
-                $scope.currentUser = null;
+                $scope.baru();
             });
         }
         $scope.remove = function(x){
                 $scope.users = UserService.query();
             });
         }
+        $scope.isClean = function(){
+            return angular.equals($scope.original, $scope.currentUser);
+        }
     }])
 ;

File belajar-restful-web/src/main/webapp/js/aplikasi-service.js

     .factory('ApplicationConfigService', ['$resource', '$http', function($resource, $http){
         var service = {
             applicationConfig: $resource('/config/:configId'),
-            get: function(param){ return this.applicationConfig.get(param) }, 
+            get: function(param, callback){ return this.applicationConfig.get(param, callback) }, 
             query: function(){ return this.applicationConfig.query() },
             save: function(obj){
                 if(obj.id == null){
     .factory('SystemMenuService', ['$resource', '$http', function($resource, $http){
         var service = {
             menu: $resource('/menu/:id'),
-            get: function(param){ return this.menu.get(param) }, 
+            get: function(param, callback){ return this.menu.get(param, callback) }, 
             query: function(){ return this.menu.query() },
             save: function(obj){
                 if(obj.id == null){
     .factory('PermissionService', ['$resource', '$http', function($resource, $http){
         var service = {
             permission: $resource('/permission/:id'),
-            get: function(param){ return this.permission.get(param) }, 
+            get: function(param, callback){ return this.permission.get(param, callback) }, 
             query: function(){ return this.permission.query() },
             save: function(obj){
                 if(obj.id == null){
     .factory('RoleService', ['$resource', '$http', function($resource, $http){
         var service = {
             role: $resource('/role/:id'),
-            get: function(param){ return this.role.get(param) }, 
+            get: function(param, callback){ return this.role.get(param, callback) }, 
             query: function(){ return this.role.query() },
             save: function(obj){
                 if(obj.id == null){
     .factory('UserService', ['$resource', '$http', function($resource, $http){
         var service = {
             user: $resource('/user/:id'),
-            get: function(param){ return this.user.get(param) }, 
+            get: function(param, callback){ return this.user.get(param, callback) }, 
             query: function(){ return this.user.query() },
             save: function(obj){
                 if(obj.id == null){

File belajar-restful-web/src/main/webapp/pages/system/config.html

 
 <div class="span5 well-large">
     <h1>Form Konfigurasi</h1>
-    <form class="form-horizontal">
-        <div class="control-group">
+    <form class="form-horizontal" name="formEdit">
+        <div class="control-group" ng-class="{error: formEdit.name.$invalid}">
             <label class="control-label" for="name">Nama : &nbsp;</label>
-            <input type="text" id="name" name="name" placeholder="Nama Konfigurasi" ng-model="currentConfig.name">
+            <input type="text" id="name" name="name" placeholder="Nama Konfigurasi" ng-model="currentConfig.name" required>
+            <span ng-show="formEdit.name.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.label.$invalid}">
             <label class="control-label" for="label">Label : &nbsp;</label>
-            <input type="text" id="label" name="label" placeholder="Label Konfigurasi" ng-model="currentConfig.label">
+            <input type="text" id="label" name="label" placeholder="Label Konfigurasi" ng-model="currentConfig.label" required>
+            <span ng-show="formEdit.label.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.value.$invalid}">
             <label class="control-label" for="value">Nilai : &nbsp;</label>
-            <input type="text" id="value" name="value" placeholder="Nilai Konfigurasi" ng-model="currentConfig.value">
+            <input type="text" id="value" name="value" placeholder="Nilai Konfigurasi" ng-model="currentConfig.value" required>
+            <span ng-show="formEdit.value.$error.required" class="help-inline">Harus diisi</span>
         </div>
         <div class="form-actions">
-            <button type="submit" class="btn btn-primary" ng-click="simpan()">Simpan</button>
+            <button type="submit" class="btn btn-primary" ng-click="simpan()" ng-disabled="isClean() || formEdit.$invalid">Simpan</button>
             <button type="button" class="btn" ng-click="baru()">Batal</button>
         </div>
     </form>

File belajar-restful-web/src/main/webapp/pages/system/menu.html

 <div class="row">
 <div class="span10 well-large">
     <h1>Form Menu</h1>
-    <form class="form-horizontal">
-        <div class="control-group">
+    <form class="form-horizontal" name="formEdit">
+        <div class="control-group" ng-class="{error: formEdit.label.$invalid}">
             <label class="control-label" for="label">Label : &nbsp;</label>
-            <input type="text" id="label" name="label" placeholder="Label Menu" ng-model="currentMenu.label">
+            <input type="text" id="label" name="label" placeholder="Label Menu" ng-model="currentMenu.label" required>
+            <span ng-show="formEdit.label.$error.required" class="help-inline">Harus diisi</span>
         </div>
         <div class="control-group">
             <label class="control-label" for="action">Action : &nbsp;</label>
                 <option ng-repeat="menu in parentSelection" value="{{menu.id}}">{{menu.label}}</option>
             </select>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.level.$invalid}">
             <label class="control-label" for="level">Level : &nbsp;</label>
-            <input type="text" id="level" name="level" placeholder="Level" ng-model="currentMenu.level">
+            <input type="text" id="level" name="level" placeholder="Level" ng-model="currentMenu.level" required>
+            <span ng-show="formEdit.level.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.level.$invalid}">
             <label class="control-label" for="order">Order : &nbsp;</label>
-            <input type="text" id="order" name="order" placeholder="Order" ng-model="currentMenu.order">
+            <input type="text" id="order" name="order" placeholder="Order" ng-model="currentMenu.order" required>
+            <span ng-show="formEdit.order.$error.required" class="help-inline">Harus diisi</span>
         </div>
         <div class="form-actions">
-            <button type="submit" class="btn btn-primary" ng-click="simpan()">Simpan</button>
+            <button type="submit" class="btn btn-primary" ng-click="simpan()" ng-disabled="isClean() || formEdit.$invalid">Simpan</button>
             <button type="button" class="btn" ng-click="baru()">Batal</button>
         </div>
     </form>

File belajar-restful-web/src/main/webapp/pages/system/permission.html

 
 <div class="span5 well-large">
     <h1>Form Permission</h1>
-    <form class="form-horizontal">
-        <div class="control-group">
+    <form class="form-horizontal" name="formEdit">
+        <div class="control-group" ng-class="{error: formEdit.label.$invalid}">
             <label class="control-label" for="label">Label : &nbsp;</label>
-            <input type="text" id="label" name="label" placeholder="Label Permission" ng-model="currentPermission.label">
+            <input type="text" id="label" 
+                   name="label" 
+                   placeholder="Label Permission" 
+                   ng-model="currentPermission.label"
+                   required>
+            <span ng-show="formEdit.label.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.value.$invalid}">
             <label class="control-label" for="value">Nilai : &nbsp;</label>
-            <input type="text" id="value" name="value" placeholder="Nilai Permission" ng-model="currentPermission.value">
+            <input type="text" 
+                   id="value" 
+                   name="value" 
+                   placeholder="Nilai Permission" 
+                   ng-model="currentPermission.value"
+                   required>
+            <span ng-show="formEdit.value.$error.required" class="help-inline">Harus diisi</span>
         </div>
         <div class="form-actions">
-            <button type="submit" class="btn btn-primary" ng-click="simpan()">Simpan</button>
+            <button type="submit" class="btn btn-primary" ng-click="simpan()" ng-disabled="isClean() || formEdit.$invalid">Simpan</button>
             <button type="button" class="btn" ng-click="baru()">Batal</button>
         </div>
     </form>

File belajar-restful-web/src/main/webapp/pages/system/role.html

 
     <div class="span5 well-large">
         <h1>Form Role</h1>
-        <form class="form-horizontal">
-            <div class="control-group">
+        <form class="form-horizontal" name="formEdit">
+            <div class="control-group" ng-class="{error: formEdit.label.$invalid}">
                 <label class="control-label" for="name">Nama : &nbsp;</label>
-                <input type="text" id="name" name="name" placeholder="Nama Role" ng-model="currentRole.name">
+                <input type="text" id="name" name="name" placeholder="Nama Role" ng-model="currentRole.name" required>
+                <span ng-show="formEdit.name.$error.required" class="help-inline">Harus diisi</span>
             </div>
             <div class="control-group">
                 <label class="control-label" for="description">Keterangan : &nbsp;</label>
                 <input type="text" id="description" name="description" placeholder="Keterangan" ng-model="currentRole.description">
             </div>
             <div class="form-actions">
-                <button type="submit" class="btn btn-primary" ng-click="simpan()">Simpan</button>
+                <button type="submit" class="btn btn-primary" ng-click="simpan()" ng-disabled="isClean() || formEdit.$invalid">Simpan</button>
                 <button type="button" class="btn" ng-click="baru()">Batal</button>
             </div>
         </form>

File belajar-restful-web/src/main/webapp/pages/system/user.html

 
 <div class="span5 well-large">
     <h1>Form User</h1>
-    <form class="form-horizontal">
-        <div class="control-group">
+    <form class="form-horizontal" name="formEdit">
+        <div class="control-group" ng-class="{error: formEdit.fullname.$invalid}">
             <label class="control-label" for="fullname">Nama : &nbsp;</label>
-            <input type="text" id="fullname" name="fullname" placeholder="Nama Lengkap" ng-model="currentUser.fullname">
+            <input type="text" id="fullname" name="fullname" placeholder="Nama Lengkap" ng-model="currentUser.fullname" required>
+            <span ng-show="formEdit.fullname.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.username.$invalid}">
             <label class="control-label" for="username">Username : &nbsp;</label>
-            <input type="text" id="username" name="username" placeholder="Nama User" ng-model="currentUser.username">
+            <input type="text" id="username" name="username" placeholder="Nama User" ng-model="currentUser.username" required>
+            <span ng-show="formEdit.username.$error.required" class="help-inline">Harus diisi</span>
         </div>
-        <div class="control-group">
+        <div class="control-group" ng-class="{error: formEdit.password.$invalid}">
             <label class="control-label" for="password">Password : &nbsp;</label>
-            <input type="password" id="password" name="password" placeholder="Password" ng-model="currentUser.password">
+            <input type="password" id="password" name="password" placeholder="Password" ng-model="currentUser.password" required>
+            <span ng-show="formEdit.password.$error.required" class="help-inline">Harus diisi</span>
         </div>
         <div class="control-group">
             <label class="control-label" for="active">Aktif : &nbsp;</label>
           </select>
         </div>
         <div class="form-actions">
-            <button type="submit" class="btn btn-primary" ng-click="simpan()">Simpan</button>
+            <button type="submit" class="btn btn-primary" ng-click="simpan()" ng-disabled="isClean() || formEdit.$invalid">Simpan</button>
             <button type="button" class="btn" ng-click="baru()">Batal</button>
         </div>
     </form>

File belajar-restful-web/src/test/java/com/artivisi/belajar/restful/ui/controller/ApplicationConfigControllerTestIT.java

 /**
  * Copyright (C) 2011 ArtiVisi Intermedia <info@artivisi.com>
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
  *
- *         http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
  */
 package com.artivisi.belajar.restful.ui.controller;
 
 import com.artivisi.belajar.restful.domain.ApplicationConfig;
+import com.artivisi.belajar.restful.domain.User;
 import static com.jayway.restassured.RestAssured.given;
 import static com.jayway.restassured.RestAssured.with;
 import com.jayway.restassured.authentication.FormAuthConfig;
 import org.springframework.web.client.RestTemplate;
 
 public class ApplicationConfigControllerTestIT {
-	private String target = "http://localhost:10000/config";
-	private String login = "http://localhost:10000/j_spring_security_check";
-
-	@Test
-	public void testSaveUpdateDelete() {
-
-		String id = testSave(target);
-		System.out.println("Id : " + id);
-		testGetExistingById(id, "coba", "Konfigurasi Percobaan", "test");
-		testUpdateExisting(id, "coba", "Konfigurasi Percobaan 001", "test123");
-		testGetExistingById(id, "coba", "Konfigurasi Percobaan 001", "test123");
-		testDeleteExistingById(id);
-	}
-
-	private String testSave(String target) {
-		ApplicationConfig config = new ApplicationConfig();
-		config.setName("coba");
-		config.setLabel("Konfigurasi Percobaan");
-		config.setValue("test");
-
-		String location = given()
-                        .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                        .body(config).contentType(ContentType.JSON)
-				.expect().statusCode(201).when().post(target)
-				.getHeader("Location");
-
-		assertNotNull(location);
-		assertTrue(location.startsWith(target));
-
-		String[] locationSplit = location.split("/");
-		String id = locationSplit[locationSplit.length - 1];
-
-		return id;
-	}
-
-	private void testGetExistingById(String id, String name, String label,
-			String value) {
-		with().header("Accept", "application/json")
-                        .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                        .expect()
-                        .statusCode(200)
-                        .body("name", equalTo(name), "label", equalTo(label), "value",
-                                equalTo(value)).when().get(target + "/" + id);
-	}
-
-	private void testUpdateExisting(String id, String name, String label,
-			String value) {
-		ApplicationConfig config = new ApplicationConfig();
-		config.setName(name);
-		config.setLabel(label);
-		config.setValue(value);
-                
-		given()
-                        .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                        .body(config).contentType(ContentType.JSON).expect()
-				.statusCode(200).when().put(target + "/" + id);
-	}
-
-	private void testDeleteExistingById(String id) {
-            given().auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-            .expect().statusCode(200).when().delete(target + "/" + id);
-
-		given().auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                        .expect().statusCode(404).when().get(target + "/" + id);
-	}
-
-	@Test
-	public void testGetExistingConfigById() {
-		with().header("Accept", "application/json")
-                    .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                    .expect()
-                    .statusCode(200)
-                    .body("id", equalTo("abc123"), 
-                                    "name",	equalTo("applicationname"), 
-                                    "label", equalTo("Application Name"), 
-                                    "value", equalTo("Belajar Restful")).when()
-                    .get(target + "/" + "abc123");
-	}
-
-	@Test
-	public void testGetNonExistentConfigById() {
-            with()
-                 .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-		.expect().statusCode(404).when().get(target + "/" + "/nonexistentconfig");
-	}
-
-	@Test
-	public void testFindAll() {
-            with()
-                .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
+    private static final String username = "endy";
+    private static final String password = "123";
+
+    private String target = "http://localhost:10000/config";
+    private String login = "http://localhost:10000/j_spring_security_check";
+
+    @Test
+    public void testSaveInvalid() {
+        ApplicationConfig u = new ApplicationConfig();
+
+        given()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .body(u).contentType(ContentType.JSON)
+                .expect().statusCode(400).when().post(target);
+    }
+
+    @Test
+    public void testSaveUpdateDelete() {
+
+        String id = testSave(target);
+        System.out.println("Id : " + id);
+        testGetExistingById(id, "coba", "Konfigurasi Percobaan", "test");
+        testUpdateExisting(id, "coba", "Konfigurasi Percobaan 001", "test123");
+        testGetExistingById(id, "coba", "Konfigurasi Percobaan 001", "test123");
+        testDeleteExistingById(id);
+    }
+
+    private String testSave(String target) {
+        ApplicationConfig config = new ApplicationConfig();
+        config.setName("coba");
+        config.setLabel("Konfigurasi Percobaan");
+        config.setValue("test");
+
+        String location = given()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .body(config).contentType(ContentType.JSON)
+                .expect().statusCode(201).when().post(target)
+                .getHeader("Location");
+
+        assertNotNull(location);
+        assertTrue(location.startsWith(target));
+
+        String[] locationSplit = location.split("/");
+        String id = locationSplit[locationSplit.length - 1];
+
+        return id;
+    }
+
+    private void testGetExistingById(String id, String name, String label,
+            String value) {
+        with().header("Accept", "application/json")
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .expect()
+                .statusCode(200)
+                .body("name", equalTo(name), "label", equalTo(label), "value",
+                equalTo(value)).when().get(target + "/" + id);
+    }
+
+    private void testUpdateExisting(String id, String name, String label,
+            String value) {
+        ApplicationConfig config = new ApplicationConfig();
+        config.setName(name);
+        config.setLabel(label);
+        config.setValue(value);
+
+        given()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .body(config).contentType(ContentType.JSON).expect()
+                .statusCode(200).when().put(target + "/" + id);
+    }
+
+    private void testDeleteExistingById(String id) {
+        given().auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .expect().statusCode(200).when().delete(target + "/" + id);
+
+        given().auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .expect().statusCode(404).when().get(target + "/" + id);
+    }
+
+    @Test
+    public void testGetExistingConfigById() {
+        with().header("Accept", "application/json")
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .expect()
+                .statusCode(200)
+                .body("id", equalTo("abc123"),
+                "name", equalTo("applicationname"),
+                "label", equalTo("Application Name"),
+                "value", equalTo("Belajar Restful")).when()
+                .get(target + "/" + "abc123");
+    }
+
+    @Test
+    public void testGetNonExistentConfigById() {
+        with()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .expect().statusCode(404).when().get(target + "/" + "/nonexistentconfig");
+    }
+
+    @Test
+    public void testFindAll() {
+        with()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
                 .header("Accept", "application/json").expect().statusCode(200)
                 .body("id", hasItems("abc123", "def456")).when().get(target);
-	}
-	
-	@Test
-	public void testSearch() {
-		with()
-                    .header("Accept", "application/json")
-                    .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-                    .param("search", "name")
-                    .expect().statusCode(200)
-                    .body("id", hasItems("abc123")).when().get(target);
-		
-		with()
-		.header("Accept", "application/json")
-                .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
-		.param("search", "xx")
-		.expect().statusCode(200)
-		.when().get(target);
-	}
-
-	@Test
-	public void testUploadFile() {
-            given()
-                .auth().form("endy", "123", new FormAuthConfig(login, "j_username", "j_password"))
+    }
+
+    @Test
+    public void testSearch() {
+        with()
+                .header("Accept", "application/json")
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .param("search", "name")
+                .expect().statusCode(200)
+                .body("id", hasItems("abc123")).when().get(target);
+
+        with()
+                .header("Accept", "application/json")
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+                .param("search", "xx")
+                .expect().statusCode(200)
+                .when().get(target);
+    }
+
+    @Test
+    public void testUploadFile() {
+        given()
+                .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
                 .multiPart("foto", new File("src/test/resources/foto-endy.jpg"))
-                .multiPart("cv",	"cv-endy.pdf", ApplicationConfig.class.getResourceAsStream("/resume-endy-en.pdf"))
+                .multiPart("cv", "cv-endy.pdf", ApplicationConfig.class.getResourceAsStream("/resume-endy-en.pdf"))
                 .formParam("keterangan", "File Endy")
-            .expect()
+                .expect()
                 .body(
-                    "keterangan", is("success"), 
-                    "cv", is("success"),
-                    "keterangan", is("success")
-                )
-            .when()
-                    .post(target+ "/" +"/abc123/files");
-	}
-	
-	@SuppressWarnings("unchecked")
-	@Test
-	public void testUploadPakaiRestTemplate(){
-            RestTemplate rest = new RestTemplate();
-            
-            String jsessionid = rest.execute(login, HttpMethod.POST,
-            new RequestCallback() {
-                @Override
-                public void doWithRequest(ClientHttpRequest request) throws IOException {
-                 request.getBody().write("j_username=endy&j_password=123".getBytes());
-                }
-            }, new ResponseExtractor<String>() {
-                @Override
-                public String extractData(ClientHttpResponse response) throws IOException {
-                    List<String> cookies = response.getHeaders().get("Cookie");
-
-                    // assuming only one cookie with jsessionid as the only value
-                    if (cookies == null) {
-                        cookies = response.getHeaders().get("Set-Cookie");
+                "keterangan", is("success"),
+                "cv", is("success"),
+                "keterangan", is("success"))
+                .when()
+                .post(target + "/" + "/abc123/files");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testUploadPakaiRestTemplate() {
+        RestTemplate rest = new RestTemplate();
+
+        String jsessionid = rest.execute(login, HttpMethod.POST,
+                new RequestCallback() {
+                    @Override
+                    public void doWithRequest(ClientHttpRequest request) throws IOException {
+                        request.getBody().write(("j_username="+username+"&j_password="+password).getBytes());
                     }
+                }, new ResponseExtractor<String>() {
+            @Override
+            public String extractData(ClientHttpResponse response) throws IOException {
+                List<String> cookies = response.getHeaders().get("Cookie");
+
+                // assuming only one cookie with jsessionid as the only value
+                if (cookies == null) {
+                    cookies = response.getHeaders().get("Set-Cookie");
+                }
 
-                    String cookie = cookies.get(cookies.size() - 1);
+                String cookie = cookies.get(cookies.size() - 1);
 
-                    int start = cookie.indexOf('=');
-                    int end = cookie.indexOf(';');
+                int start = cookie.indexOf('=');
+                int end = cookie.indexOf(';');
 
-                    return cookie.substring(start + 1, end);
-                }
-            });
-            
-            
-		
-		MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>();
-		form.add("foto", new FileSystemResource("src/test/resources/foto-endy.jpg"));
-		form.add("Filename", "cv-endy.pdf");
-		form.add("cv", new FileSystemResource("src/test/resources/resume-endy-en.pdf"));
-		form.add("keterangan", "File Endy");
-		Map<String, String> result = rest.postForObject(target+"/abc123/files;jsessionid=" + jsessionid, form, Map.class);
-		
-		assertEquals("success", result.get("cv"));
-		assertEquals("success", result.get("foto"));
-		assertEquals("success", result.get("keterangan"));
-	}
+                return cookie.substring(start + 1, end);
+            }
+        });
+
+
+
+        MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>();
+        form.add("foto", new FileSystemResource("src/test/resources/foto-endy.jpg"));
+        form.add("Filename", "cv-endy.pdf");
+        form.add("cv", new FileSystemResource("src/test/resources/resume-endy-en.pdf"));
+        form.add("keterangan", "File Endy");
+        Map<String, String> result = rest.postForObject(target + "/abc123/files;jsessionid=" + jsessionid, form, Map.class);
+
+        assertEquals("success", result.get("cv"));
+        assertEquals("success", result.get("foto"));
+        assertEquals("success", result.get("keterangan"));
+    }
 }

File belajar-restful-web/src/test/java/com/artivisi/belajar/restful/ui/controller/MenuControllerTestIT.java

     private String password = "123";
 
     @Test
+    public void testSaveInvalid(){
+        Menu u = new Menu();
+        
+        given()
+            .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+            .body(u).contentType(ContentType.JSON)
+            .expect().statusCode(400).when().post(target);
+    }
+    
+    @Test
     public void testSaveUpdateDelete() {
 
         Menu x = new Menu();

File belajar-restful-web/src/test/java/com/artivisi/belajar/restful/ui/controller/PermissionControllerTestIT.java

     private String password = "123";
 
     @Test
+    public void testSaveInvalid(){
+        Permission u = new Permission();
+        
+        given()
+            .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+            .body(u).contentType(ContentType.JSON)
+            .expect().statusCode(400).when().post(target);
+    }
+    
+    @Test
     public void testSaveUpdateDelete() {
 
         Permission x = new Permission();

File belajar-restful-web/src/test/java/com/artivisi/belajar/restful/ui/controller/RoleControllerTestIT.java

     private String password = "123";
 
     @Test
+    public void testSaveInvalid(){
+        Role u = new Role();
+        
+        given()
+            .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+            .body(u).contentType(ContentType.JSON)
+            .expect().statusCode(400).when().post(target);
+    }
+    
+    @Test
     public void testSaveUpdateDelete() {
 
         Role x = new Role();

File belajar-restful-web/src/test/java/com/artivisi/belajar/restful/ui/controller/UserControllerTestIT.java

     private String password = "123";
 
     @Test
+    public void testSaveInvalid(){
+        User u = new User();
+        
+        given()
+            .auth().form(username, password, new FormAuthConfig(login, "j_username", "j_password"))
+            .body(u).contentType(ContentType.JSON)
+            .expect().statusCode(400).when().post(target);
+    }
+    
+    @Test
     public void testSaveUpdateDelete() {
 
         Role r = new Role();