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 | +} | ... | ... |