Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could be able to avoid business validation? #11

Closed
jmirc opened this issue Apr 21, 2014 · 14 comments
Closed

Could be able to avoid business validation? #11

jmirc opened this issue Apr 21, 2014 · 14 comments
Labels

Comments

@jmirc
Copy link

jmirc commented Apr 21, 2014

The validationRules json contains front-end and business rules. For example I have a User JPA which contains some contraints related to spring security tokens. These contraints are used by the backend but not at the front-end level.

It could be great to be able to avoid specific contraints from the validationRules.

@marcelstoer
Copy link
Collaborator

Not sure I understand this feature request. Only the supported annotations and the configured custom annotations are processed.

It's our assumption that all validations in this set should also be applied in the front-end. Do you disagree?

@jmirc
Copy link
Author

jmirc commented Apr 22, 2014

I defined a User entity. The entity defines multiples attributes. Some (login, password, firstName, lastName, email) must be validated at the front-end level and others (authorities, persistentTokens) should be validated at the backend level.

I am looking a way to avoid the servlet to send backend rules to the front-end

@Entity
@Table(name = "T_USER")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class User implements Serializable {

    @NotNull
    @Size(min = 0, max = 50)
    @Id
    private String login;

    @JsonIgnore
    @Size(min = 0, max = 100)
    private String password;

    @Size(min = 0, max = 50, message = "settings.messages.validate.firstname.maxlength")
    @Column(name = "first_name")
    private String firstName;

    @Size(min = 0, max = 50, message = "settings.messages.validate.lastname.maxlength")
    @Column(name = "last_name")
    private String lastName;

    @Email(message = "settings.messages.validate.email.invalid")
    @Size(min = 0, max = 100, message = "settings.messages.validate.email.maxlength")
    private String email;

    @JsonIgnore
    @ManyToMany
    @JoinTable(
            name = "T_USER_AUTHORITY",
            joinColumns = {@JoinColumn(name = "login", referencedColumnName = "login")},
            inverseJoinColumns = {@JoinColumn(name = "name", referencedColumnName = "name")})
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<Authority> authorities;

    @JsonIgnore
    @OneToMany(mappedBy = "user")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<PersistentToken> persistentTokens;

} 

@marcelstoer
Copy link
Collaborator

Hmm, still don't get it...

Neither authorities nor persistentTokens have annotations that match what I said in my last comment:

Only the supported annotations and the configured custom annotations are processed.

In fact, they don't have Bean Validation annotations at all. When you request

avoid the servlet to send backend rules to the front-end

are you implicitly saying that the current version of the valdr Bean Validation returns annotations place on either of the two fields?

@jmirc
Copy link
Author

jmirc commented Apr 22, 2014

Yes the servlet returns rules because the Authority and the PersistentToken classes are two entities which contain JSR-303 annotations even if there is no Bean Validation annotations

@marcelstoer
Copy link
Collaborator

Ok, I'm beginning to see the issue. Authority and PersistentToken reside in the same package structure as User (i.e. in one of the sub packages you configured to be scanned), correct? Can you provide them in order for me to build a test case that resembles yours as closely as possible?

@jmirc
Copy link
Author

jmirc commented Apr 22, 2014

I am looking to see if I will add your project as a standard stack in JHipster (http://jhipster.github.io/)

You can use the JHipster sample as example (https://github.com/jhipster/jhipster-sample-app)
Here are the changes that need to be applied to integrate this library.

pom.xml (Add a new dependency)

    <dependency>
      <groupId>com.github.valdr</groupId>
      <artifactId>valdr-bean-validation</artifactId>
      <version>1.0.0-rc2</version>
   </dependency>

bower.js (Add a new dependency)

   "valdr": "~0.1.1"

src/main/java/com/mycompany/myapp/config/WebConfigurer.java (Initialize the ValidationRules Servlet)

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        log.info("Web application configuration, using profiles: {}", Arrays.toString(env.getActiveProfiles()));
        EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);

        initMetrics(servletContext, disps);
        if (env.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
            initStaticResourcesProductionFilter(servletContext, disps);
            initCachingHttpHeadersFilter(servletContext, disps);
        }
        initGzipFilter(servletContext, disps);
        if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT)) {
            initH2Console(servletContext);
        }
        initJsr303Support(servletContext);

        log.info("Web application fully configured");
    }

    /**
     * Initializes to support JSR-303 for AngularJs model
     */
    private void initJsr303Support(ServletContext servletContext) {
        log.debug("Initialize AngularJs model JSR-303 support");
        ServletRegistration.Dynamic hsr303Servlet = servletContext.addServlet("valdr", new ValidationRulesServlet());
        hsr303Servlet.addMapping("/api/validationRules");
        hsr303Servlet.setInitParameter("modelPackages", "com.mycompany.myapp.domain");
        hsr303Servlet.setInitParameter("corsAllowOriginPattern", "*");

    }

Let me know if you need more information.

@philippd
Copy link
Collaborator

I just integrated valdr in JHipster to test this. The problem is that Authorityand PersistentToken reside in the configured model package:

hsr303Servlet.setInitParameter("modelPackages", "com.mycompany.myapp.domain");

Therefore you end up with a validation rules JSON that contains those two classes as they are considered part of your domain model AND have JSR303-annotated fields.

If you don't want those classes to be part of the JSON returned to the client, just move them to another package. com.mycompany.myapp.securitywould make more sense to me, as these are not real domain classes.

This would fix the issue for your case, but it would probably still make sense to be able to exclude classes that are in the modelPackages (by either listing them in a servlet init parameter or annotating those classes) in case you have classes in the domain package which you never use in a client form.

We will discuss this and update the issue.

@marcelstoer
Copy link
Collaborator

If you don't want those classes to be part of the JSON returned to the client, just move them to another package.

Also, keep in mind that the modelPackages is plural...you can configure a comma-separated string of packages.

If we decide to support exclusion in any form I'd propose the following:

  • close this issue
  • create a new one for exclusion of classes
  • create a new one for exclusion of fields

However, I still dither whether we really need this:

  • the packages that represent the domain model shouldn't contain classes that don't belong to the domain model
  • if you have classes in the domain packages that are never "used" in the front-end then so what, they can still be in the JSON, no harm done
  • if you have a field in a domain class that you don't want to have validated by valdr in the front-end then you simply don't map it (different ng-model value), may be a bit cumbersome :-/

@philippd what's your take on this?

@philippd
Copy link
Collaborator

I think that excluding classes and fields is a feature that we should support. It may well be that you have domain objects that you don't want publicly known for whatever reason. Even if it's only to keep the JSON structure small for performance reasons...

On field level we should probably also support ignoring fields which are annotated with @JsonIgnore since these never even get sent to the client. And we already have a Jackson dependency anyway and therefore have this class in the classpath.

close this issue
create a new one for exclusion of classes
create a new one for exclusion of fields

Yep, that's fine if you agree with the above.

@jmirc
Copy link
Author

jmirc commented Apr 28, 2014

The support of @jsonIgnore will fix all the issues in term of moving classes outside the default package, adding a new annotation to exclude a class or a field. I don't see any advantages to exclude a class if the exclusion can be supported at the field level.

@philippd
Copy link
Collaborator

philippd commented Jun 4, 2014

I created new issues for the individual tasks identified in the discussion above: #17, #18, #19

@philippd philippd closed this as completed Jun 4, 2014
@marcelstoer
Copy link
Collaborator

@jmirc exclusion of classes and fields is part of v1.1 which was released a few days ago.

@jgribonvald
Copy link

@jmirc & @philippd have you an example of project working with a jhipster project ? I'm trying to integrate valdr but i do'nt know where I'm wrong i'm getting such error in browser console: TypeError: Cannot set property 'valdr' of undefined

@jgribonvald
Copy link

I've found my problem, sorry for that...

I'm working with angular 1.2.x not 1.3 and Firefox provide a better error log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants