Commit 2545cbeada0ff90edf780976195c9c5708eb0e50
1 parent
10e37220
Exists in
master
Implementação do tratamento de erros de validação
Showing
8 changed files
with
293 additions
and
75 deletions
Show diff stats
archetype/html-rest/src/main/resources/archetype-resources/src/main/java/rest/BookmarkREST.java
| ... | ... | @@ -37,7 +37,7 @@ public class BookmarkREST { |
| 37 | 37 | @GET |
| 38 | 38 | @Path("{id}") |
| 39 | 39 | @Produces("application/json") |
| 40 | - public Bookmark load(@PathParam("id") Long id) throws Exception { | |
| 40 | + public Bookmark load(@PathParam("id") Long id) { | |
| 41 | 41 | Bookmark result = bc.load(id); |
| 42 | 42 | |
| 43 | 43 | if (result == null) { |
| ... | ... | @@ -52,9 +52,7 @@ public class BookmarkREST { |
| 52 | 52 | @Produces("text/plain") |
| 53 | 53 | @Consumes("application/json") |
| 54 | 54 | public Response insert(Bookmark entity, @Context UriInfo uriInfo) { |
| 55 | - if (entity.getId() != null) { | |
| 56 | - throw new BadRequestException(); | |
| 57 | - } | |
| 55 | + checkId(entity); | |
| 58 | 56 | |
| 59 | 57 | String id = bc.insert(entity).getId().toString(); |
| 60 | 58 | URI location = uriInfo.getRequestUriBuilder().path(id).build(); |
| ... | ... | @@ -67,29 +65,24 @@ public class BookmarkREST { |
| 67 | 65 | @Transactional |
| 68 | 66 | @Consumes("application/json") |
| 69 | 67 | public void update(@PathParam("id") Long id, Bookmark entity) { |
| 70 | - if (entity.getId() != null) { | |
| 71 | - throw new BadRequestException(); | |
| 72 | - } | |
| 73 | - | |
| 74 | - if (bc.load(id) == null) { | |
| 75 | - throw new NotFoundException(); | |
| 76 | - } | |
| 68 | + checkId(entity); | |
| 69 | + load(id); | |
| 77 | 70 | |
| 78 | 71 | entity.setId(id); |
| 79 | 72 | bc.update(entity); |
| 80 | 73 | } |
| 81 | - | |
| 82 | - @DELETE | |
| 83 | - @Transactional | |
| 84 | - @Consumes("application/json") | |
| 85 | - public void delete(List<Long> ids) { | |
| 86 | - bc.delete(ids); | |
| 87 | - } | |
| 88 | 74 | |
| 89 | 75 | @DELETE |
| 90 | 76 | @Path("{id}") |
| 91 | 77 | @Transactional |
| 92 | 78 | public void delete(@PathParam("id") Long id) { |
| 79 | + load(id); | |
| 93 | 80 | bc.delete(id); |
| 94 | 81 | } |
| 82 | + | |
| 83 | + private void checkId(Bookmark entity) throws BadRequestException { | |
| 84 | + if (entity.getId() != null) { | |
| 85 | + throw new BadRequestException(); | |
| 86 | + } | |
| 87 | + } | |
| 95 | 88 | } | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/interceptor/RequiredPermissionInterceptor.java
| ... | ... | @@ -46,7 +46,7 @@ import org.slf4j.Logger; |
| 46 | 46 | import br.gov.frameworkdemoiselle.security.RequiredPermission; |
| 47 | 47 | |
| 48 | 48 | /** |
| 49 | - * Intercepts calls with {@code @RequiredPermission} annotations. | |
| 49 | + * Intercepts calls with {@code @Validate} annotations. | |
| 50 | 50 | * |
| 51 | 51 | * @author SERPRO |
| 52 | 52 | */ | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/security/RequiredPermissionInterceptor.java
| ... | ... | @@ -51,7 +51,7 @@ import br.gov.frameworkdemoiselle.util.ResourceBundle; |
| 51 | 51 | import br.gov.frameworkdemoiselle.util.Strings; |
| 52 | 52 | |
| 53 | 53 | /** |
| 54 | - * Intercepts calls with {@code @RequiredPermission} annotations. | |
| 54 | + * Intercepts calls with {@code @Validate} annotations. | |
| 55 | 55 | * |
| 56 | 56 | * @author SERPRO |
| 57 | 57 | */ |
| ... | ... | @@ -66,7 +66,7 @@ public class RequiredPermissionInterceptor implements Serializable { |
| 66 | 66 | private static transient Logger logger; |
| 67 | 67 | |
| 68 | 68 | /** |
| 69 | - * Gets the values for both resource and operation properties of {@code @RequiredPermission}. Delegates to | |
| 69 | + * Gets the values for both resource and operation properties of {@code @Validate}. Delegates to | |
| 70 | 70 | * {@code SecurityContext} check permissions. If the user has the required permission it executes the mehtod, |
| 71 | 71 | * otherwise throws an exception. Returns what is returned from the intercepted method. If the method's return type |
| 72 | 72 | * is {@code void} returns {@code null}. |
| ... | ... | @@ -99,12 +99,12 @@ public class RequiredPermissionInterceptor implements Serializable { |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | /** |
| 102 | - * Returns the resource defined in {@code @RequiredPermission} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 102 | + * Returns the resource defined in {@code @Validate} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 103 | 103 | * annotation or the class name itself |
| 104 | 104 | * |
| 105 | 105 | * @param ic |
| 106 | 106 | * the {@code InvocationContext} in which the method is being called |
| 107 | - * @return the resource defined in {@code @RequiredPermission} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 107 | + * @return the resource defined in {@code @Validate} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 108 | 108 | * annotation or the class name itself |
| 109 | 109 | */ |
| 110 | 110 | private String getResource(InvocationContext ic) { |
| ... | ... | @@ -127,12 +127,12 @@ public class RequiredPermissionInterceptor implements Serializable { |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | /** |
| 130 | - * Returns the operation defined in {@code @RequiredPermission} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 130 | + * Returns the operation defined in {@code @Validate} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 131 | 131 | * annotation or the method's name itself |
| 132 | 132 | * |
| 133 | 133 | * @param ic |
| 134 | 134 | * the {@code InvocationContext} in which the method is being called |
| 135 | - * @return the operation defined in {@code @RequiredPermission} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 135 | + * @return the operation defined in {@code @Validate} annotation, the name defined in {@code @AmbiguousQualifier} | |
| 136 | 136 | * annotation or the method's name itself |
| 137 | 137 | */ |
| 138 | 138 | private String getOperation(InvocationContext ic) { | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/validation/Validate.java
0 → 100644
| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | +/* | |
| 2 | + * Demoiselle Framework | |
| 3 | + * Copyright (C) 2010 SERPRO | |
| 4 | + * ---------------------------------------------------------------------------- | |
| 5 | + * This file is part of Demoiselle Framework. | |
| 6 | + * | |
| 7 | + * Demoiselle Framework is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | |
| 9 | + * as published by the Free Software Foundation. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | |
| 17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | |
| 18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | |
| 19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | |
| 20 | + * ---------------------------------------------------------------------------- | |
| 21 | + * Este arquivo é parte do Framework Demoiselle. | |
| 22 | + * | |
| 23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | |
| 24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | |
| 25 | + * do Software Livre (FSF). | |
| 26 | + * | |
| 27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | |
| 28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | |
| 29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | |
| 30 | + * para maiores detalhes. | |
| 31 | + * | |
| 32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | |
| 33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | |
| 34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | |
| 35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | |
| 36 | + */ | |
| 37 | +package br.gov.frameworkdemoiselle.validation; | |
| 38 | + | |
| 39 | +import static java.lang.annotation.ElementType.METHOD; | |
| 40 | +import static java.lang.annotation.ElementType.TYPE; | |
| 41 | +import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
| 42 | + | |
| 43 | +import java.lang.annotation.Inherited; | |
| 44 | +import java.lang.annotation.Retention; | |
| 45 | +import java.lang.annotation.Target; | |
| 46 | + | |
| 47 | +import javax.interceptor.InterceptorBinding; | |
| 48 | + | |
| 49 | +@Inherited | |
| 50 | +@InterceptorBinding | |
| 51 | +@Target({ METHOD, TYPE }) | |
| 52 | +@Retention(RUNTIME) | |
| 53 | +public @interface Validate { | |
| 54 | + | |
| 55 | +} | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/validation/ValidateInterceptor.java
0 → 100644
| ... | ... | @@ -0,0 +1,80 @@ |
| 1 | +/* | |
| 2 | + * Demoiselle Framework | |
| 3 | + * Copyright (C) 2010 SERPRO | |
| 4 | + * ---------------------------------------------------------------------------- | |
| 5 | + * This file is part of Demoiselle Framework. | |
| 6 | + * | |
| 7 | + * Demoiselle Framework is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public License version 3 | |
| 9 | + * as published by the Free Software Foundation. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public License version 3 | |
| 17 | + * along with this program; if not, see <http://www.gnu.org/licenses/> | |
| 18 | + * or write to the Free Software Foundation, Inc., 51 Franklin Street, | |
| 19 | + * Fifth Floor, Boston, MA 02110-1301, USA. | |
| 20 | + * ---------------------------------------------------------------------------- | |
| 21 | + * Este arquivo é parte do Framework Demoiselle. | |
| 22 | + * | |
| 23 | + * O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou | |
| 24 | + * modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação | |
| 25 | + * do Software Livre (FSF). | |
| 26 | + * | |
| 27 | + * Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA | |
| 28 | + * GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou | |
| 29 | + * APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português | |
| 30 | + * para maiores detalhes. | |
| 31 | + * | |
| 32 | + * Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título | |
| 33 | + * "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/> | |
| 34 | + * ou escreva para a Fundação do Software Livre (FSF) Inc., | |
| 35 | + * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA. | |
| 36 | + */ | |
| 37 | +package br.gov.frameworkdemoiselle.validation; | |
| 38 | + | |
| 39 | +import java.io.Serializable; | |
| 40 | +import java.util.HashSet; | |
| 41 | +import java.util.Set; | |
| 42 | + | |
| 43 | +import javax.interceptor.AroundInvoke; | |
| 44 | +import javax.interceptor.Interceptor; | |
| 45 | +import javax.interceptor.InvocationContext; | |
| 46 | +import javax.validation.ConstraintViolation; | |
| 47 | +import javax.validation.ConstraintViolationException; | |
| 48 | +import javax.validation.Validation; | |
| 49 | +import javax.validation.Validator; | |
| 50 | +import javax.validation.ValidatorFactory; | |
| 51 | + | |
| 52 | +/** | |
| 53 | + * Intercepts calls with {@code @Validate} annotations. | |
| 54 | + * | |
| 55 | + * @author SERPRO | |
| 56 | + */ | |
| 57 | +@Validate | |
| 58 | +@Interceptor | |
| 59 | +public class ValidateInterceptor implements Serializable { | |
| 60 | + | |
| 61 | + private static final long serialVersionUID = 1L; | |
| 62 | + | |
| 63 | + @AroundInvoke | |
| 64 | + public Object manage(final InvocationContext ic) throws Exception { | |
| 65 | + Set<ConstraintViolation<?>> violations = new HashSet<ConstraintViolation<?>>(); | |
| 66 | + | |
| 67 | + for (Object params : ic.getParameters()) { | |
| 68 | + ValidatorFactory dfv = Validation.buildDefaultValidatorFactory(); | |
| 69 | + Validator validator = dfv.getValidator(); | |
| 70 | + | |
| 71 | + violations.addAll(validator.validate(params)); | |
| 72 | + } | |
| 73 | + | |
| 74 | + if (!violations.isEmpty()) { | |
| 75 | + throw new ConstraintViolationException(violations); | |
| 76 | + } | |
| 77 | + | |
| 78 | + return ic.proceed(); | |
| 79 | + } | |
| 80 | +} | ... | ... |
impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/PreconditionFailedException.java
0 → 100644
| ... | ... | @@ -0,0 +1,95 @@ |
| 1 | +package br.gov.frameworkdemoiselle; | |
| 2 | + | |
| 3 | +import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; | |
| 4 | + | |
| 5 | +import java.util.HashSet; | |
| 6 | +import java.util.Set; | |
| 7 | + | |
| 8 | +import javax.xml.ws.http.HTTPException; | |
| 9 | + | |
| 10 | +public class PreconditionFailedException extends HTTPException { | |
| 11 | + | |
| 12 | + private static final long serialVersionUID = 1L; | |
| 13 | + | |
| 14 | + private Set<Violation> violations = new HashSet<Violation>(); | |
| 15 | + | |
| 16 | + public PreconditionFailedException() { | |
| 17 | + super(SC_PRECONDITION_FAILED); | |
| 18 | + } | |
| 19 | + | |
| 20 | + public PreconditionFailedException addViolation(String property, String message) { | |
| 21 | + this.violations.add(new Violation(property, message)); | |
| 22 | + return this; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public Set<Violation> getViolations() { | |
| 26 | + return violations; | |
| 27 | + } | |
| 28 | + | |
| 29 | + public static class Violation { | |
| 30 | + | |
| 31 | + public String property; | |
| 32 | + | |
| 33 | + public String message; | |
| 34 | + | |
| 35 | + public Violation() { | |
| 36 | + } | |
| 37 | + | |
| 38 | + public Violation(String property, String message) { | |
| 39 | + this.property = property; | |
| 40 | + this.message = message; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public String getProperty() { | |
| 44 | + return property; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public void setProperty(String property) { | |
| 48 | + this.property = property; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public String getMessage() { | |
| 52 | + return message; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public void setMessage(String message) { | |
| 56 | + this.message = message; | |
| 57 | + } | |
| 58 | + | |
| 59 | + @Override | |
| 60 | + public int hashCode() { | |
| 61 | + final int prime = 31; | |
| 62 | + int result = 1; | |
| 63 | + result = prime * result + ((message == null) ? 0 : message.hashCode()); | |
| 64 | + result = prime * result + ((property == null) ? 0 : property.hashCode()); | |
| 65 | + return result; | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public boolean equals(Object obj) { | |
| 70 | + if (this == obj) | |
| 71 | + return true; | |
| 72 | + if (obj == null) | |
| 73 | + return false; | |
| 74 | + if (getClass() != obj.getClass()) | |
| 75 | + return false; | |
| 76 | + Violation other = (Violation) obj; | |
| 77 | + if (message == null) { | |
| 78 | + if (other.message != null) | |
| 79 | + return false; | |
| 80 | + } else if (!message.equals(other.message)) | |
| 81 | + return false; | |
| 82 | + if (property == null) { | |
| 83 | + if (other.property != null) | |
| 84 | + return false; | |
| 85 | + } else if (!property.equals(other.property)) | |
| 86 | + return false; | |
| 87 | + return true; | |
| 88 | + } | |
| 89 | + | |
| 90 | + @Override | |
| 91 | + public String toString() { | |
| 92 | + return this.property + " " + this.message; | |
| 93 | + } | |
| 94 | + } | |
| 95 | +} | ... | ... |
impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/internal/implementation/ConstraintViolationExceptionMapper.java
| 1 | -//package br.gov.frameworkdemoiselle.internal.implementation; | |
| 2 | -// | |
| 3 | -//import java.util.Arrays; | |
| 4 | -// | |
| 5 | -//import javax.validation.ConstraintViolation; | |
| 6 | -//import javax.validation.ConstraintViolationException; | |
| 7 | -//import javax.ws.rs.core.Context; | |
| 8 | -//import javax.ws.rs.core.Response; | |
| 9 | -//import javax.ws.rs.ext.ExceptionMapper; | |
| 10 | -//import javax.ws.rs.ext.Provider; | |
| 11 | -// | |
| 12 | -//@Provider | |
| 13 | -//public class ConstraintViolationExceptionMapper implements ExceptionMapper<Exception> { | |
| 14 | -// | |
| 15 | -// @Context | |
| 16 | -// private Response response; | |
| 17 | -// | |
| 18 | -// @Override | |
| 19 | -// public Response toResponse(Exception exception) { | |
| 20 | -// | |
| 21 | -// Throwable rootCause = exception; | |
| 22 | -// while (rootCause != null) { | |
| 23 | -// if (rootCause instanceof ConstraintViolationException) { | |
| 24 | -// break; | |
| 25 | -// } | |
| 26 | -// | |
| 27 | -// rootCause = rootCause.getCause(); | |
| 28 | -// } | |
| 29 | -// | |
| 30 | -// if (rootCause != null) { | |
| 31 | -// for (ConstraintViolation<?> violation : ((ConstraintViolationException) rootCause) | |
| 32 | -// .getConstraintViolations()) { | |
| 33 | -// String parts[] = violation.getPropertyPath().toString().split("\\.|\\[|\\]\\."); | |
| 34 | -// String property = null; | |
| 35 | -// | |
| 36 | -// if (parts.length > 1) { | |
| 37 | -// property = parts[1]; | |
| 38 | -// | |
| 39 | -// for (String part : Arrays.copyOfRange(parts, 2, parts.length)) { | |
| 40 | -// property += "." + part; | |
| 41 | -// } | |
| 42 | -// } | |
| 43 | -// | |
| 44 | -// System.out.println(property); | |
| 45 | -// } | |
| 46 | -// } | |
| 47 | -// | |
| 48 | -// return null; | |
| 49 | -// } | |
| 50 | -// } | |
| 1 | +package br.gov.frameworkdemoiselle.internal.implementation; | |
| 2 | + | |
| 3 | +import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; | |
| 4 | + | |
| 5 | +import java.util.Iterator; | |
| 6 | + | |
| 7 | +import javax.validation.ConstraintViolation; | |
| 8 | +import javax.validation.ConstraintViolationException; | |
| 9 | +import javax.ws.rs.core.Response; | |
| 10 | +import javax.ws.rs.ext.ExceptionMapper; | |
| 11 | +import javax.ws.rs.ext.Provider; | |
| 12 | + | |
| 13 | +import br.gov.frameworkdemoiselle.PreconditionFailedException; | |
| 14 | + | |
| 15 | +@Provider | |
| 16 | +public class ConstraintViolationExceptionMapper implements ExceptionMapper<ConstraintViolationException> { | |
| 17 | + | |
| 18 | + @Override | |
| 19 | + public Response toResponse(ConstraintViolationException exception) { | |
| 20 | + PreconditionFailedException failed = new PreconditionFailedException(); | |
| 21 | + | |
| 22 | + for (Iterator<ConstraintViolation<?>> iter = exception.getConstraintViolations().iterator(); iter.hasNext();) { | |
| 23 | + ConstraintViolation<?> violation = iter.next(); | |
| 24 | + failed.addViolation(violation.getPropertyPath().toString(), violation.getMessage()); | |
| 25 | + } | |
| 26 | + | |
| 27 | + return Response.status(PRECONDITION_FAILED).entity(failed.getViolations()).build(); | |
| 28 | + } | |
| 29 | +} | ... | ... |
impl/extension/rest/src/main/java/br/gov/frameworkdemoiselle/internal/implementation/PreconditionFailedExceptionMapper.java
0 → 100644
| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | +package br.gov.frameworkdemoiselle.internal.implementation; | |
| 2 | + | |
| 3 | +import javax.ws.rs.core.Response; | |
| 4 | +import javax.ws.rs.ext.ExceptionMapper; | |
| 5 | +import javax.ws.rs.ext.Provider; | |
| 6 | + | |
| 7 | +import br.gov.frameworkdemoiselle.PreconditionFailedException; | |
| 8 | + | |
| 9 | +@Provider | |
| 10 | +public class PreconditionFailedExceptionMapper implements ExceptionMapper<PreconditionFailedException> { | |
| 11 | + | |
| 12 | + @Override | |
| 13 | + public Response toResponse(PreconditionFailedException exception) { | |
| 14 | + return Response.status(exception.getStatusCode()).entity(exception.getViolations()).build(); | |
| 15 | + } | |
| 16 | +} | ... | ... |