türsteher für bohnen
TRANSCRIPT
![Page 1: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/1.jpg)
Bean Validation mit JSR-303
Türsteher für Bohnen
![Page 2: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/2.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 2
Holisticon wurde 2006 gegründet.
Das operative Geschäft inDeutschland haben wir zum1. Januar 2007 aufgenommen.
Wir sind in Großraum Hamburg vertreten.
Wir beraten Konzerne und große mittelständische Unternehmen.
Wir sind ein Tochterunternehmen der schwedischenSigma-Gruppe.
Holisticon AG
![Page 3: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/3.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 3
Unser Weltbild
![Page 4: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/4.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 4
Validierung in üblichen Architekturen
JSR-303
Domänenspezifische Datentypen
Integration Spring MVC JSF2 JFace Data Binding
Service Boundary Validation
Offene Punkte
Agenda
![Page 5: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/5.jpg)
Validierung in üblichen Architekturen
![Page 6: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/6.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 6
Spezifika der Java Enterprise Welt Mehrschicht-Architekturen Bit-Schieber-Anwendung Benutzer-Interaktion Verwendung von (vielen verschiedenen) Frameworks
Validierung Eingabevalidierung Design-by-Contract Daten-Integrität
Übliche Architekturen
![Page 7: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/7.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 7
EJB +JSF 2
EJB +RCP
Spring + JSF 2Spring MVC
Übliche Architekturen
SWT
JFaceView JSF Page
JSF ControllerController Integration
Serviceschnittstellen
Session BeansSpring Beans
![Page 8: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/8.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 8
Übliche Architekturen
Spring MVC Lifecycle Controller
Submitted Form
Data Binding
Validation
Business Logic
View Resolver
Model and View
Dispatcher Servlet
![Page 9: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/9.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 9
Übliche Architekturen
Spring MVC Validatoren (klassischer Ansatz)public class ZipCodeValidator implements Validator { boolean supports(Class clazz) { return String.class.equals(clazz); } public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, “zipcode", “zipcode.empty"); String z = (String) obj;
if (z.length() != 5) { e.rejectValue(”zipcode", ”wrong.size”); } }}
![Page 10: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/10.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 10
Übliche Architekturen
JSF2 Validatoren (klassischer Ansatz)
RestoreView
ApplyRequestValues
ProcessValidation
UpdateModel Values
InvokeApplication
Render Response
![Page 11: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/11.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 11
Übliche Architekturen
JSF2 Validatoren (klassischer Ansatz)
<h:inputText … > <f:validator validatorId="ZipcodeValidator" /></h:inputText>
@FacesValidator("ZipcodeValidator")public class ZipcodeValidator implements Validator {
public void validate(FacesContext ctx, UIComponent component, Object value) throws ValidatorException {
if (value instanceof String) { String zipCode = (String) value; if (zipCode == null || zipCode.length() != 5) { throw new ValidatorException(new FacesMessage( FacesMessage.SEVERITY_ERROR, "Wrong zip code", null)); } } }}
![Page 12: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/12.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 12
Übliche Architekturen
JFace Data Binding Validatoren (klassischer Ansatz)
SWT/JFace Listeners
Property Change Listeners
Model-to-TargetUpdate Strategy
Target-to-ModelUpdate Strategy
Observable
Target
Observable
Model ValidatorenValidatoren
Konverter
Konverter
![Page 13: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/13.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 13
Übliche Architekturen
JFace Data Binding Validatoren (klassischer Ansatz)public class ZipCodeComposite extends Composite {
public void createBinding(DataBindingContext dbc) { IObservableValue observableModel = … ISWTObservableValue observableTarget = …
UpdateValueStrategy t2m = new UpdateValueStrategy(); t2m.setAfterConvertValidator(new IValidator() { public IStatus validate(Object value) { if ((String) value == null || ((String) value).length() != 5) { return ValidationStatus.error("Wrong zip code"); } return ValidationStatus.ok(); } });
dbc.bindValue(observableTarget, observableModel, t2m, null); }}
![Page 14: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/14.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 14
Übliche Architekturen
JPA Hooks (klassischer Ansatz)@ExcludeDefaultInterceptorspublic class PersistenceValidationListener {
@PrePersist @PreUpdate @PreRemove public void validateMe(Object entity) {
if (entity instanceof Address) { String zipCode = ((Address)entity).getZip(); if (zipCode == null || zipCode.length() != 5) { throw new IllegalArgumentException(“Wrong zip code”); } } }}
![Page 15: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/15.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 15
Übliche Architekturen
Validatoren für jedes Framework Schicht System
Validierung als Teil der Anwendungslogik
![Page 16: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/16.jpg)
Bean Validation JSR-303
![Page 17: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/17.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 17
Bean Validation
Idee Validierungsregeln an Daten Offener JCP Standard (JSR-303) Open Source Implementierung Definiert eine Menge von Constraints Definiert eine Validation API
Standard Constraint Annotationen
public class ZipCode { @Pattern(regexp = "[0-9]*") @Size(min=5, max=5) private String content;}
@AssertFalse@AssertTrue@DecimalMin(value)@DecimalMax(calue)@Digits(integer, fraction)@Future@Min(value)@Max(value)
@NotNull@Null@Past@Pattern(regexp, flags)@Size(min, max)@Valid
![Page 18: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/18.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 18
Bean Validation
@Valid
![Page 19: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/19.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 19
Bean Validation
Validation APIpublic class ValidatorHelper {
private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static void validate(Object object) { Set<ConstraintViolation<Object>> violations = validator.validate(object); if (violations.size() > 0) { StringBuffer buf = new StringBuffer("constraint violations in") .append(object.getClass().getName() + "["); for (ConstraintViolation<Object> violation : violations) { buf.append("\"").append(violation.getPropertyPath()).append("\" ") .append(violation.getMessage()).append(" (invalidValue=\"") .append(violation.getInvalidValue()).append("\"); "); } throw new IllegalArgumentException(buf.append("]").toString()); } }}
![Page 20: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/20.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 20
Bean Validation
Eigene Constraints
@Target({ FIELD, PARAMETER })@Retention(RUNTIME)@Constraint(validatedBy = {})@Pattern(regexp = "[0-9]*")@Size(min = 5, max = 5)@ReportAsSingleViolationpublic @interface ZipcodeConstraint {
String message() default "{Zipcode.invalid_zipcode}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};}
![Page 21: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/21.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 21
Bean Validation
Eigener Validator@Constraint(validatedBy = {ZipcodeValidator.class})public @interface ZipcodeConstraint { // …}
public class ZipcodeValidator implements ConstraintValidator<ZipcodeConstraint, String> { private String message; public void initialize(ZipcodeConstraint annotation) { message = annotation.message(); } public boolean isValid(String value, ConstraintValidatorContext ctx) { if (value.length() != 5) { ctx.buildConstraintViolationWithTemplate(message) .addConstraintViolation(); return false; } return true; }}
![Page 22: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/22.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 22
Bean Validation
Validation Groups, Constraint Listpublic class ZipCode { @Pattern.List({ @Pattern(regexp = "[0-9]*"), @Pattern(regexp = "[0-9\\*]*", groups = { Search.class }) }) @Size.List({ @Size(min=5, max=5), @Size(min=1, max=5, groups = { Search.class }) }) @NotNull(groups = { Default.class, Search.class }) private String content;}
public class ValidatorHelper { public static void validate(Class<?>[] groups, Object object) { Set<ConstraintViolation<Object>> violations = validator.validate(object, groups); // … }}
![Page 23: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/23.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 23
Bean Validation
JSF 2 Zero-config Standardvalidator
JPA Mittels JPA Hooks Spezielle Graph-Traverser
![Page 24: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/24.jpg)
Domänenspezifische Datentypen
![Page 25: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/25.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 25
Domänenspezifische Typen
/** * Domain specific type */public class Customer {
@Valid @NotNull private Name name;
@Enumerated(EnumType.STRING) @NotNull private Gender gender;
// …}
![Page 26: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/26.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 26
Domänenspezifische Typen
/** * Domain specific type */public class Customer {
// … @Valid @NotNull private Address postalAddress;
@Valid @NotNull private Address billingAddress;
// …}
![Page 27: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/27.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 27
Domänenspezifische Typen
public class Address {
private String addressLine1;
private String addressLine2;
@Valid private ZipCode zip;
@Valid private City city;
}
![Page 28: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/28.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 28
Domänenspezifische Typen
public class ZipCode {
@Pattern.List({ @Pattern(regexp = "[0-9]*"), @Pattern(regexp = "[0-9\\*]*", groups = Search.class) }) @Size(min=1, max=5) @NotNull(groups = { Default.class, Search.class}) @Column(name = "zip") private String content;
// …}
![Page 29: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/29.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 29
Domänenspezifische Typen
Domänenspezifische Datentypen Datencontainer mit Semantik Stellt schichtenübergreifende Typisierung sicher
Konvertierung Konvertierung für UI (String <-> Object <-> String) Konvertierung für DB (O/R-Mapping)
Validierung Ist eng mit Format / Semantik der Daten verbunden Muss in die Frameworks integriert werden
![Page 30: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/30.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 30
Domänenspezifische Typen
UI
Business Services
O/R Mapping
![Page 31: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/31.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 31
Domänenspezifische Typen
Domänenspezifische Typen mit JSR-303? Konvertierung Validierung
![Page 32: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/32.jpg)
Spring MVC Integration
![Page 33: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/33.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 33
Spring MVC
Property Editor Support (Konverter)public class ZipCodeBinder extends PropertyEditorSupport { public String getAsText() { return (getValue() == null ? "" : ((ZipCode) getValue()).getContent()); }
public void setAsText(final String text) throws IllegalArgumentException { if (text != null && !text.isEmpty()) { ZipCode zipCode = new ZipCode(text); setValue(zipCode); } else { setValue(null); } }}
![Page 34: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/34.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 34
Spring MVC
Controller@RequestMapping(value="/customer.html", method = RequestMethod.PUT)public String processForm(@Valid Customer customer, BindingResult result, Map<String, Object> model) {
if (result.hasErrors()) { // […] return "form"; } Customer savedCustomer = customerService.createCustomer(customer); // […] model.put("customer", savedCustomer); return "form";}
![Page 35: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/35.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 35
Spring MVC
View<form:form method="put" action="customer.html" commandName="customer">
<fieldset> <form:label path="postalAddress.zip„>PLZ:</form:label> <form:input path="postalAddress.zip" /> <form:errors path="postalAddress.zip" /> <input type="submit" value="Create" /> </fieldset>
</form:form>
![Page 36: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/36.jpg)
JSF2 Integration
![Page 37: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/37.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 37
JSF Integration
Apache MyFaces Extensions Validator (ExtVal)
Konverter@FacesConverter(forClass=ZipCode.class)public class ZipcodeConverter implements Converter {
public Object getAsObject(FacesContext ctx, UIComponent comp, String value) { if (value == null) return null; return new ZipCode(value); }
public String getAsString(FacesContext ctx, UIComponent comp, Object value) { return ((ZipCode)value).getContent(); }}
![Page 38: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/38.jpg)
JFace Data Binding Integration
![Page 39: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/39.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 39
JFace Data Binding
Bindingpublic class ZipCodeComposite extends Composite {
public void createBinding(DataBindingContext dbc) {
// […]
UpdateValueStrategy t2m = new UpdateValueStrategy(); UpdateValueStrategy m2t = new UpdateValueStrategy(); m2t.setConverter(new ZipCode2StringConverter()); t2m.setConverter(new String2ZipCodeConverter()); t2m.setAfterConvertValidator(new BeanValidator());
dbc.bindValue(observableTarget, observableModel, t2m, m2t); }}
![Page 40: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/40.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 40
JFace Data Binding
IConverterpublic class ZipCode2StringConverter implements IConverter {
public Object getToType() { return String.class; } public Object getFromType() { return ZipCode.class; }
public Object convert(Object fromObject) { ZipCode zipCode = (ZipCode) fromObject; if (zipCode == null) { return null; } return zipCode.getContent(); }}
![Page 41: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/41.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 41
JFace Data Binding
Validatorpublic class BeanValidator implements IValidator {
private ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
public IStatus validate(Object value) { Set<ConstraintViolation<Object>> violations = factory.getValidator() .validate(value, new Class<?>[] { Default.class });
if (violations.size() > 0) { List<IStatus> statusList = new ArrayList<IStatus>(); for (ConstraintViolation<Object> cv : violations) { statusList.add(ValidationStatus.error(cv.getMessage())); } return new MultiStatus(Activator.PLUGIN_ID, IStatus.ERROR, statusList .toArray(new IStatus[statusList.size()]), "Validation errors", null); }
return ValidationStatus.ok(); }}
![Page 42: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/42.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 42
Domänenspezifische Typen
Erkenntnisse Wiederverwendbarkeit Semantische Typsicherheit Validierungslogikkapselung Trennung der Verantwortlichkeit
Spezielle Konverter Konverter verletzen die Kapselungsgrenzen
![Page 43: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/43.jpg)
Service Boundary Validation
![Page 44: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/44.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 44
Service Boundary Validation
Motivation Richtlinien für Schnittstellendesign Design-by-Contract Transparenz für den Entwickler
Grundprinzip Aspekt / Interceptor Validierung der Methodenparameter Validierung der Rückgabewerte
![Page 45: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/45.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 45
Service Boundary Validation
JNDI /DI Resolver BeanWrapper
Bean InterceptorClient
Business Interface
doBusiness
doBusiness
validateParams
validateResult
![Page 46: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/46.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 46
Service Boundary Validation
EJB Interceptorpublic class ServiceValidationInterceptor {
@AroundInvoke public Object validate(InvocationContext context) throws Exception {
Method method = context.getMethod(); Object[] args = context.getParameters(); validateParams(args, method);
Object result = context.proceed();
if (result != null) { validateResult(result); }
return result; }}
![Page 47: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/47.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 47
Service Boundary Validation
Spring Aspektpublic class ServiceValidationAspect { public void validateArguments(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); … } public void validateResult(JoinPoint joinPoint, Object retVal) { … }}
<beans[…] > <bean id="bvAspect" class="….aspect.ServiceValidationAspect" /> <aop:config> <aop:pointcut id="bv" expression="execution(* *.*(..))" /> <aop:aspect ref="bvAspect"> <aop:before pointcut-ref="bv" method="validateArguments" /> <aop:after-returning pointcut-ref="bv" returning="retVal" method="validateResult" /> </aop:aspect> </aop:config></beans>
![Page 48: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/48.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 48
Service Boundary Validation
Was ist mit Gruppenvalidierung?public interface Search extends ValidationGroup {
}
@Target({ ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface ValidationAdvice {
Class<? extends ValidationGroup>[] value();
}
public interface CustomerService {
public List<Customer> getAllCustomers();
@ValidationAdvice(Search.class) public List<Customer> searchCustomer(CustomerSearchParameters criteria);}
![Page 49: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/49.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 49
Service Boundary Validation
Gruppenvalidierungpublic void validateArguments(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs(); Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Class<?> groups = new Class<?>[] { Default.class }; ValidationAdvice advice = method.getAnnotation(ValidationAdvice.class); if (advice != null) { groups = advice.value(); }
ValidatorHelper.requireValidated(groups, args);}
![Page 50: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/50.jpg)
Offene Punkte
![Page 51: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/51.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 51
Offene Punkte und Ausblick
JSR-303 Bean Validation ist praxistauglich!
Sinnvolle Ergänzung: Apache MyFaces ExtVal!
Domänenspezifische Typen zur Kapselung!
Was ist mit Konvertern?
Conditional/Cross Validation mit EL?
Was ist mit JAX-WS/JAX-B?
![Page 52: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/52.jpg)
Türsteher für Bohnen | Oliver Ochs, Simon Zambrovski | 52
![Page 53: Türsteher für Bohnen](https://reader036.vdocuments.pub/reader036/viewer/2022062406/55bab1c2bb61eb7f058b45dd/html5/thumbnails/53.jpg)
Vielen Dank!
http://blog.holisticon.de/