Giter VIP home page Giter VIP logo

Comments (43)

brentryan avatar brentryan commented on May 26, 2024 2

The only downside to this approach that we've found is that we need to use getFoo() instead of just foo() in order for validations to work. Not a huge deal but this really forces us to use getter syntax everywhere for consistency. I'd prefer to just use foo() everywhere and validations still work.

from immutables.

making avatar making commented on May 26, 2024 2

It is not a direct solution to this issue, but if you are interested in alternatives, please refer to the following.

YAVI is another validation library that works out of the box for Immutables as bellow.

import am.ik.yavi.builder.ValidatorBuilder;
import am.ik.yavi.core.Validator;
import org.immutables.value.Value;

@Value.Immutable
public abstract class User {
	public abstract String name();

	public abstract String email();

	public abstract int age();

	public static Validator<User> validator = ValidatorBuilder.<User>of()
			.constraint(User::name, "name", c -> c.notNull()
					.lessThanOrEqual(20))
			.constraint(User::email, "email", c -> c.notNull()
					.greaterThanOrEqual(5)
					.lessThanOrEqual(50)
					.email())
			.constraint(User::age, "age", c -> c.notNull()
					.greaterThanOrEqual(0)
					.lessThanOrEqual(200))
			.build();
}
final User user = ImmutableUser.builder()
		.name("aa")
		.email("[email protected]")
		.age(10)
		.build();
final ConstraintViolations violations = User.validator.validate(user);

Hope this is interesting to the folks in this thread.

from immutables.

cal101 avatar cal101 commented on May 26, 2024 1

Convinced. ;-)

But:
In my experience the annotation based validation interfaces and classes are an entangled mix of different responsibilities.
Maybe I missed something or it was changed recently but the last time I checked

  • The annotations are the single source of information. (What about abstracting the source of the information from the information itself?)
  • The code for extracting that information is tightly coupled with the application. (What about an information extractor and working on some abstract information?)
  • No way to feed the validator code with same info as annotations but from other sources.

Your second point contradicts my view of the world:

with support for complex custom validation that e.g. has to read a database for additional info).

Do you have a pointer to that? I remember trying to do exactly that and failing.

from immutables.

elucash avatar elucash commented on May 26, 2024 1

I am not sure if JSR-303 validation fits at all, even with generated getters...

Surely, we cannot expect that existing implementations of the bean validation will handle immutable object gracefully, but the original value in such integration appeared to be in a fact of reuse of the annotations/API and validation extensibility model specified by JSR-303.

As of now there are no plans to work on JSR-303 integration, as in most cases the preferred approach to validation is to use appropriate types and preconditions. I mean if you received a message with an email String, then you convert it to Email value object which in by definition is valid once constructed (it cannot be constructed in invalid state), and so on. Of course, this approach cannot cover all of use cases, and some support classes to collect and propagate violations should still be used, as opposed to throwing a runtime exception on first violation encountered.

I cannot be sure it will work, but you may try to use @Value.Modifiable generated companion objects (with Style.create = "new" to have public non-final class & constructor). This way you can annotate abstract value type and validate modifiable object, rather than immutable implementation. There are .from and .toImmutable methods to convert modifiable from and to immutable object.

from immutables.

bernd avatar bernd commented on May 26, 2024 1

Hibernate validator supports custom getter property selection strategies since version 6.1. That makes it possible to validate immutables that don't use the bean style gettern methods. (getFoo) The documentation even includes a ready to use example for this. https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-getter-property-selection-strategy

from immutables.

elucash avatar elucash commented on May 26, 2024 1

@nasibulloh It's hard to tell what's wrong, here's couple of observations:

  1. When using @Check verification, you would call verification for each instance ever constructed, so using @Validated @RequestBody is either pointless or duplicate validation. You could either remove @Validated or remove @Check + VALIDATOR to validate only on request (not on every construction).

  2. You're using non-getter methods (which I prefer too), but It seems that Bean Validation spec do not like it. Hibernate Validator implementation (check if you use HV or something else) supports validating non-getter methods. Your choice here is to either rename methods to getters (device() -> getDevice()), at least temporarily, just to see if it works, or, or rather "then" you can find a way to enable validation of non-getter methods. See https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-configuring-validator-factory, It has element <executable-type>NON_GETTER_METHODS</executable-type> or something like that. Hibernate Validator could use some sort of programmatic configuration (instead or in addition to xml)

ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
        .configure()
        // <-- maybe can be configured here, never tried
        .buildValidatorFactory();

Validator validator = validatorFactory.getValidator();

(quick advice: don't create many factory instances or validators, at least not for each object separately. Validators are thread safe, so you can use shared constant for all objects, or just validate per request with @Validated, but then the instance will be managed by Spring, so to configure it you would need to inject custom configuration somewhere or use xml for Hibernate Validator specific property which mentioned above)

from immutables.

elucash avatar elucash commented on May 26, 2024

Hi, I glad you enjoy using Immutables!
I already tripped on this get setter situation. We have not completely decided if we should specially treat any prefixes in attribute names, because it complicates other tools in the chain, having them to special-case on attribute names in builders (and so on) in order to generate code that consumes value objects. (But it's not something that we closed and not discussing anymore, still gathering feedback and use-cases and comparing trade-offs)

Newly released version 0.18 does large amount of refinements of already existed functionality, therefore you should try if this will solve interoperability:

  • @GenerateGetters annotation that generates bean-style getters. You should define attributes without prefixes and annotate it with javax.validation annotations. Getters will be generated in immutable subclass and annotation processor will copy all annotations from original attribute methods to generated getters.

Let me know if it works for you!

If there will be any issues with JAX-RS integration, just file a bug. Also see #15, #27

from immutables.

toellrich avatar toellrich commented on May 26, 2024

That should do the trick. Thanks!

from immutables.

elucash avatar elucash commented on May 26, 2024

I'm not closing this as I want to investigate a more complete, compile-time integration. We thought about it some time ago, and some research was made. currently focus is on reimplementing core processing. but I definitely want to return to this.

from immutables.

elucash avatar elucash commented on May 26, 2024

There's issue opened to investigate and implement support get/set accessors #33

from immutables.

DavidLeoni avatar DavidLeoni commented on May 26, 2024

Hi,

regarding validation api support, I noticed that when @Valid annotation is added to a getter, the example below throws on exception upon validation because @Valid tag is copied to generated Immutable class getter and this upsets standard hibernate implementation (tried hibernate-validator 5.1.3.Final and Immutables 2.0.16):

class Person {

}

@Value.Immutable
abstract class Car {
    @Valid
    public abstract Person getDriver();
}

public class TestGen {

    @Test
    public void testValidate() {        
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
         Set<ConstraintViolation<ImmutableCar>> constraintViolations
                = validator.validate(ImmutableCar.builder().driver(new Person()).build());
    }

}

This is the thrown exception:

javax.validation.ConstraintDeclarationException: HV000131: A method return value must not be marked for cascaded validation more than once in a class hierarchy, but the following two methods are marked as such: public abstract it.davidleoni.experiments.immutables.test.Person it.davidleoni.experiments.immutables.test.Car.getDriver(), public it.davidleoni.experiments.immutables.test.Person it.davidleoni.experiments.immutables.test.ImmutableCar.getDriver(). 

An ad-hoc solution might be not to copy @Valid annotation, or a generic solution might introduce a system to prevent copying of certain user-specified annotations.

from immutables.

augustotravillio avatar augustotravillio commented on May 26, 2024

Hi David
There's more generic solution for this, there's Style.passAnnotations, but it had to be fixed/expanded to work on attribute level annotations also (see #139).
As an immediate effect, annotations like Valid will not be copied automatically. I don't know when exactly we will release this, but you can try the fix with 2.1.0-SNAPSHOT available in sonatype-oss-repository (Or it could be build from this git repository).

from immutables.

DavidLeoni avatar DavidLeoni commented on May 26, 2024

Thanks for the reply - didn't know about Style.passAnnotations. For the time being I can live without Valid, maybe I will try the snapshot in tests.

David

from immutables.

elucash avatar elucash commented on May 26, 2024

BTW the passAnnotations fix was released in 2.0.17

from immutables.

bjblazko avatar bjblazko commented on May 26, 2024

I am not sure if JSR-303 validation fits at all, even with generated getters.
For example, if I deploy an application with an immutable class with a simple, say @Pattern annotation into Wildfly, I get the following runtime exception during deployment from WELD CDI:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001503: Bean class which has interceptors cannot be declared final

...and I guess it is correct. I can live with validating using the external JSR Validator (e.g. using @Value.Check) instead of using @Valid in all CDI managed services, but just having the annotations in my model class does not allow me to do so I guess.
Is there any good alternative which lets me to keep the validation specs (e.g. field constraints) defined within my class and not using external artifacts?
Immutables.org is such a great thing but sadly Bean Validation is as well and I see no way to marry those two :(

from immutables.

cal101 avatar cal101 commented on May 26, 2024

Does it really make sense to validate the immutable instance?
Either you treat it as a unvalidated container which does not care and you validate the entity after updating it from the container and before persisting it.
Or you make an already validated object immutable and so the result will be typically valid, too.
Can someone sketch a more complete use case that benefits from validation support?

from immutables.

bjblazko avatar bjblazko commented on May 26, 2024

Well, I use immutables as my "business" model and I think it quite makes sense to validate them.
One the one hand, immutables are already checked for mandatory properties, which already is a kind of validation.

On the other hand, the same motivation that led to Java Bean validation - the immutable as business object is the single point of truth - it defines what properties there are, what to do with them (fat domain model contrary to the anemic one) and how they look like (possibly depending on context as achieved via groups in JSR-303/349.
I always found it odd to have separate validating code in the frontend or while reading from persistence layer, sometimes having duplicated validation implementations or techniques. Do not get me wrong - it is correct to DO validation in these phases (aka fail early principle), but the definition should be in the business layer (here: my immutable). And this is where JSR-349 succeeds in my view:

  • Definition of validation in the core model.
  • Simple annotation based rules (with support for complex custom validation that e.g. has to read a database for additional info).
  • Context switching: validation is not uniform but depends on context, e.g. support for non-complete data while in UI but latest during persistence, you can define a stricter validation using groups.
  • No necessity to actively validate - it comes as an aspect as long as you POJO passes managed code (e.g. @Stateless classes).
  • Great framework support for validation: for example JSF and JPA directly support JSR-349 withtout hassle or usage of e.g. frontend-dedicated tooling for that purpose (like e.g. Struts Validation in those times), not to speak of handling it whenever passing methods containing the @Valid annotation in the signature.

Oh, that was longer than intended... ;) Well, I can live without implicit validation, especially JSR-349 is targeted for Java Beans - so if only it can be achieved with dirty tricks then better not, am just hoping for it ;)

Maybe this may clear up a bit. However, immutables.org is so f* great - it makes my Java life much more fun - thank your that!

from immutables.

bjblazko avatar bjblazko commented on May 26, 2024

Hi @cal101 ,

ja, I have some kind of pointer, an example project I did some long time ago, I implemented some code doing just that (i.e. adding custom code), so you could adapt this for e.g. implementing DB access etc.

...or just have a look at the other examples: Bitbucket repository

from immutables.

cal101 avatar cal101 commented on May 26, 2024

Hi!

I see what you mean. But that is not what I had in mind. We got this great generic framework for validating fields/properties, generic collection of errors, extension with custom properties and custom validators.
But: The only way to get this flexible machinery applied to some property is by adding an annotation at the source code level?
Look like spring distinguishes between the source of some information (annotation, xml, programmatic) and it's application e.g. for transaction application.
I wanted to use some of the standard validators but wanted to provide the configuration programmatically. I failed because of the tight coupling IMHO.

Edited: I was wrong here because at least Hibernate Validator supports programmatic constraints, see some later comment.

from immutables.

bjblazko avatar bjblazko commented on May 26, 2024

Ah, great to hear about that @Value.Modifiable, did not stumble upon that so far, great! Will check that, however, as I do very small applications, I am afraid that having more than one model might get to much overhead ;)

from immutables.

gunnarmorling avatar gunnarmorling commented on May 26, 2024

Hi, Bean Validation 2.0 spec lead and Hibernate Validator project lead here :) I just learned about Immutables, it's looks like a great library.

Putting my user's hat on, I think the following would be very useful to have:

  • Support for the declaration of BV constraints on value classes:

    @Value.Immutable
    @MyFoobarClassLevelConstraint
    public abstract class FoobarValue {
    
        @Min(1)
        public abstract int foo();
    
        @NotEmpty
        public abstract List<Integer> buz();
    }
    
  • Automatically validate these constraints when obtaining an instance of the value object from the builder; that way users could only ever obtain an instance of the object when it's valid in terms of its BV constraints.

I see two way to achieve the latter:

  • Copy the constraint definitions from the annotated abstract class to the corresponding fields of the implementation and validate the created instance within the build() method of the builder before returning it; a potentially invalid instance would be created that way but it would never be returned to the user, instead a ConstraintViolationException would be raised.
  • Copy the constraint definitions from the annotated abstract class to the parameters of the corresponding builder methods, e.g. foo(@Min(1) int foo) and use the method validation feature from BV 1.1 to automatically validate the parameters of the builder method upon their invocation. You'd still have to validate class-level constraints on the instantiated object within build(), though (this could be done by a specific validation group to the copy of the class-level constraints on the impl class and only validate that specific group, avoiding another validation of all the property-level constraints).

The latter would have the nice aspect of exposing the constraints right on the methods of the builder and failing early on upon passing an illegal value to a specific builder method. Thinking about it, you also could simply call Validator#validateValue() for given property values instead of relying on method validation.

Either way, it'd be great if Immutables would have built-in support for BV. If there is anything I can help with, just let me know.

from immutables.

cal101 avatar cal101 commented on May 26, 2024

As discussed before it may be useful to do validation only if requested to be able to transport the raw data using immutables + json and do the validation on the receiver side as an explicit measure
on the same data structure but in a different context.

from immutables.

gunnarmorling avatar gunnarmorling commented on May 26, 2024

I'm not totally sure whether I'm following you, but it seems it'd make sense then to propagate constraints to the object's fields so it can be validated either within the build() method or explicitly within other contexts.

Btw. (to address one facet of the discussion of constraint meta-data sources) BV also allows to declare constraints exernally using XML descriptors. Hibernate Validator (the reference implementation) additionally provides a proprietary API for declaring constraints programmatically.

from immutables.

elucash avatar elucash commented on May 26, 2024

Hi @gunnarmorling, Thank you for chiming in! I've spent some time today experimenting with BV and I think we already pretty close to say that we support BV. I don't know how much we actually need to implement on top of it to be more "complete", or we might just spend some time documenting it as is.
Ok, let's get to business. First of all there it is not clear how we will get validator instance. Therefore there should be some flexibility like take some static validator (I even don't know whether Validators are threadsafe or not) or supply instance during construction. As Immutable object may have multiple construction path (builder, constructor, deserialization), we have a validation mechanism to check preconditions uniformly, so I was playing to integrate at this point. Immutable objects may extend classes/interfaces(traits) and we can push some shared functionality there.

Here's example with static validator instance:

// Let's create reusable interface (abstract class may also be used)
interface WithDefaultValidator {
    Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
        // this check will be incorporated in each extending value class
    @Value.Check 
    default void check() {
        Set<ConstraintViolation<WithDefaultValidator>> violations = VALIDATOR.validate(this);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
}

// Let's use it
@Value.Immutable
public interface ToValidate extends WithDefaultValidator {
    @NotEmpty
    String getAttr(); // just use getter with constraint
}

// And guess what..
ImmutableToValidate obj = ImmutableToValidate.builder()
  .attr("")
  .build();
// Constraint validation exception is thrown!

I think extending shared WithDefaultValidator is pretty neat, don't require much boilerplate and self-documenting that validation is used.
If we want to supply external validator for validation or/and have it optional, we might use slightly different base interface

interface WithSuppliedValidator {
    @Nullable
    Validator getValidator();

    @Value.Check
    default void check() {
        @Nullable Validator validator = getValidator();
        if (validator != null) {
            Set<ConstraintViolation<WithSuppliedValidator>> violations = validator.validate(this);
            if (!violations.isEmpty()) {
                throw new ConstraintViolationException(violations);
            }
        }
    }
}

@Value.Immutable
interface ToValidate2 extends WithSuppliedValidator {
    @NotEmpty
    String getAttr();
}

// In this way, you optionally supply validator on construction
ImmutableToValidate2 unv = ImmutableToValidate2.builder()
    .validator(Validation.buildDefaultValidatorFactory().getValidator())
    .attr("")
    .build();
// exception will be thrown in this case also

Class level constraint worked for me too. I'm happy that accessor validation just works and I don't see a point to copy annotation to fields as fields are implementation detail (for example, java.util.Optional<String> is implemented as @Nullable String field, so some constraints might not work as expected if just copied). Needless to say that if we don't need auto-validation, we can avoid using @Value.Check method and just call validatior.validate(valueInstance) directly if it's properly annotated.

WDYT?

from immutables.

gunnarmorling avatar gunnarmorling commented on May 26, 2024

Hi, ah, I didn't know that getters are supported to. Yes, in that case you are almost there indeed. Nothing more needed then other than validating the created object after it has been instantiated. The copying approach would only be needed if you wanted to support constraints on non JavaBeans properties (foo() instead of getFoo()), too.

I even don't know whether Validators are threadsafe or not

Yes, Validator is thread-safe.

The idea of "mixing in" validator support through some base interface is neat indeed (though it creates a dependency to an Immutables-defined interface at runtime, not sure whether there is precedent for this already?). Otherwise I like the idea of just passing the validator to the builder as you did in your last example.

from immutables.

elucash avatar elucash commented on May 26, 2024

The idea of "mixing in" validator support through some base interface is neat indeed (though it creates a dependency to an Immutables-defined interface at runtime, not sure whether there is precedent for this already?)

While there are precedents of using runtime support components in Immutables, the core functionality is free of any runtime dependencies. Some people would like to have static validator, other may prefer supply one, here and there it can be handled with small variations. Either create configurable annotations with knobs or Maybe even we don't need any dependency, just document how to create such mixin and show some examples. I like bring-your-own-mixin approach better as don't want to limit people in trivial things and at the same time don't want to multiply annotation/configuration hell which can be experienced without additional "help" from Immutables.

from immutables.

cal101 avatar cal101 commented on May 26, 2024

+1 for the bring-your-own-mixin approach (cool name BTW :-): simple, self documenting, flexible

@gunnarmorling Thanks for correcting me about the alternative BV constraint sources.
OT: Is it possible to set a constraint for all "String" properties of some Type without resorting to reflection?
Background: No String property should contain control or invalid unicode chars.

from immutables.

elucash avatar elucash commented on May 26, 2024

@brentryan totally agree with the concerns. Just don't know a reasonable way to deal with it without generating additional proxies (a la ImmutableX.Json for Jackson) and so on, which is not so great solution on its own.

from immutables.

jifwin avatar jifwin commented on May 26, 2024

Any updates on this?

from immutables.

elucash avatar elucash commented on May 26, 2024

Hi @jifwin. Currently, validation is supported as is: using built-in validator (Style.validationMethod) or by using mixin approach outlined above, is there specific aspect or fix you're interested in? Known issues are that only get* methods in javabean style are validated (But Hibernate Validator v5 promised to support free-form accessors as implementation-specific feature, i.e. not in specification)

from immutables.

johno1985 avatar johno1985 commented on May 26, 2024

Ah perfect, didn't realise there was a passAnnotations style, thanks

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

Would be great to have this documented in the website read me with a few examples. As the Javax groups validation constraints seems like its really powerful for the use cases.

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

Also I am seeing warnings when using the mixin pattern

(immutables:incompat) Guava collection implementation does not allow null elements, @AllowNulls/@SkipNulls annotation will be ignored. Switch Style.jdkOnly=true to use collections that permit nulls as values

have tried variations/combinations of

    @NotNull @valid
    Set<@NotBlank String> getMitigates();

but the warnings remain. Any ways to get rid of these and still use Guava?


Running Notes for usage:

  1. Optionals (Optional<..>) should not be given a javax.validation @Nullable as it will through a warning about losing it's special treatment. Should Optional be suggested as proper usage over @nullable?
  2. Is @NotNull required on Collections? (not the inner type, but the Collection attribute) --- Validation.NONE states: "Disables null and mandatory attribute checks. Any missing primitives will be initialized to their zero-based values: false, 0, '\0'. Object references will be nulls. Any optional, default and collection attributes will be initialized with their appropriate default values regardless of this validation setting."
  3. All attributes need to have the get* prefix. aka: if you had a Attribute such as String firstName(); (interface example), then it should be changed to String getFirstName();. without the get* the attribute will not be picked up by javax.validation hibernate validator as per:
    #26 (comment)

from immutables.

elucash avatar elucash commented on May 26, 2024

@StephenOTT trying to confirm: this is happening when validationMethod=NONE right?

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

@elucash yes correct

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

@elucash you can take a look at: https://github.com/StephenOTT/charon-stix/blob/master/src/test/groovy/stix/desrialization/BundleSpec.groovy and run the test to see specific warnings when running compile

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

For anyone looking for a more complex example of the javax validation usage:

see: https://github.com/StephenOTT/charon-stix/tree/master/src/main/java/io/digitalstate/stix/validation

and: https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/sdo/objects/AttackPatternSdo.java

You can see a mix of layered/inheritance interfaces each with their own validation constraints.

You can see the Validator called here: https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/validation/SdoDefaultValidator.java

and you can see how its called using @Value.Check: https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/common/StixCommonProperties.java#L104-L111

There is also some extra flavour here with Validation Constraints being used for Default values: As a example of https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/common/StixCommonProperties.java#L50-L59, these are required fields, but there was a race condition happening with Default values (@Value.Default) and Javax Validations. So specific default values that also have specific validation requirements were moved into the default Type constraint: https://github.com/StephenOTT/charon-stix/tree/master/src/main/java/io/digitalstate/stix/validation/contraints/defaulttypevalue

Also take a look at the use of Constraint Sequences: https://github.com/StephenOTT/charon-stix/tree/master/src/main/java/io/digitalstate/stix/validation/sequences and https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/validation/SdoDefaultValidator.java#L17 and
https://github.com/StephenOTT/charon-stix/blob/master/src/main/java/io/digitalstate/stix/validation/SdoDefaultValidator.java#L24.
This lets you use Constrains as a Default Value generator using Annotations. The sequences control the order of evaluation of the constraints, so that the "Default Value constraints are always executed first / before the actual validation constraints.

from immutables.

StephenOTT avatar StephenOTT commented on May 26, 2024

@elucash did you have any insight into the #26 (comment)
(immutables:incompat) Guava collection implementation does not allow null elements, @AllowNulls/@SkipNulls annotation will be ignored. Switch Style.jdkOnly=true to use collections that permit nulls as values warnings generated during compile?

from immutables.

elucash avatar elucash commented on May 26, 2024

@StephenOTT I have the preliminary fix for this (d05304c). Can you, please, try to build the master or get the snapshot from Sonatype OSS repo to evalute the fix.

from immutables.

nasibulloh avatar nasibulloh commented on May 26, 2024

I tried to validate request as you used @elucash . But it did not work.

@Value.Immutable
@JsonDeserialize(builder = UserSignUpRequest.Builder.class)
@JsonSerialize(as = UserSignUpRequest.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@ImmutableJsonModel
@Validated
interface AbstractUserSignUpRequest {
  Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();

  @Value.Parameter
  @Pattern(regexp = RegexPatterns.PHONE_REGEX)
  String phone();

  @Value.Parameter
  @NotBlank
  String username();

  @Value.Parameter
  Optional<DeviceRegistrationRequest> device();

  @Value.Check
  default void check() {
    Set<ConstraintViolation<AbstractUserSignUpRequest>> violations = VALIDATOR.validate(this);
    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(violations);
    }
  }
}

 @PostMapping(
      value = "/sign-up",
      consumes = MediaType.APPLICATION_JSON_VALUE,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public Mono<ResponseEntity<UserCreatedResponse>> signUp(
      @Validated @RequestBody Mono<UserSignUpRequest> request) {

    return request
        .flatMap(authenticationService::signUp)
        .map(user -> ResponseEntity.status(CREATED).body(user));
  }

from immutables.

nasibulloh avatar nasibulloh commented on May 26, 2024

@elucash I tried to rename class fields, but it did not help. cause Immutable does not generate getter and setter.
In my case I dont use Hibernate and Hibernate Validators. I used javax.validation by springboot. If I use @Value.Check annotation , but in this case I cannot get access to Messagesource. I need support i18n also for validation messages

from immutables.

elucash avatar elucash commented on May 26, 2024

javax.validation is a standard API (Called "Bean Validation", JSR303, https://en.wikipedia.org/wiki/Bean_Validation), it's implemented by some library such as Hibernate Validator (not "Hibernate", but "Hibernate Validator", which was started as subproject of Hibernate, but it provides completely different framework (for JSR303), although it is designed to be used with Hibernate & JPA). Spring boot is not an implementation for it, but it can bundle said Hibernate Validator as a dependency and "auto" configure it with tons of "magic". I googled a bit, and maybe you can do something with LocalValidatorFactoryBean, but frankly you may try to just create XML configuration file https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#chapter-xml-configuration and add <executable-type>NON_GETTER_METHODS</executable-type> to the right place, I assume you can figure out xml structure from documentation.

from immutables.

Endron avatar Endron commented on May 26, 2024

I also had the issue with fields not being accessed in Spring Boot using Hibernate Validator.

It looks like this can be fixed by implementing your own custom GetterPropertySelectionStrategy and adding a Validator configured to use it to your Spring Context. Configuration can be done via XML or programatic by just defining your own Validator bean replacing the one Spring Boot auto configuration creates per default.

Here is the Hibernate Validator documentation explaining how to do the configuration;
https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-getter-property-selection-strategy

My property selection strategy looks like this:

public class ImmutablesGetterPropertySelectionStrategy implements GetterPropertySelectionStrategy {

    private final DefaultGetterPropertySelectionStrategy delegate = new DefaultGetterPropertySelectionStrategy();

    @Override
    public Optional<String> getProperty(ConstrainableExecutable executable) {
        return delegate.getProperty(executable)
                .or(
                        () -> Optional.ofNullable(executable.getParameterTypes())
                                .filter(paramTypes -> paramTypes.length == 0)
                                .map(it -> executable.getName())
                );
    }

    @Override
    public Set<String> getGetterMethodNameCandidates(String propertyName) {
        var result = new HashSet<>(delegate.getGetterMethodNameCandidates(propertyName));
        result.add(propertyName);

        return result;
    }
}

I would advise more testing before reusing it. I would call it still under investigation...

from immutables.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.