How to do Bean Validation for REST services of server plugin

Hi Experts,

I have tried this example but this is not working for REST services of JIRA serve plugin

Any sample code would be helpful.

Hi, @dchouksey89
Did you manage to solve the problem?

I have the same trouble. I want to validate Dto object when it comes to REST.

Dto:

@Getter
@Setter
@NoArgsConstructor
@XmlRootElement
public class UserDto {
    @Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
    private String name;
}

User Resource:

@Named
@Provider
@Path("/user")
public class UserResource {

   private final UserService userService;

    @Inject
    public UserResource(UserService userService) {
        this.userService= userService;
    }
    
    @POST
    @Produces(APPLICATION_JSON)
    @Consumes({APPLICATION_JSON})
    public Response create(@Valid UserDto userDto) {
        UserDto result = userService.add(userDto);
        return Response.ok().entity(result).build();
    }
}

For validation I added a dependency:

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.0.Final</version>
        </dependency>

I am using a rest client to send a JSON:

{
    "name": "w",
}

I expect that the name will not pass validation, the object will not be saved to the database and I will get a 400 error with my error message. However, the object is saved and I don’t get an error. And I retrieved STATUS 200 and JSON:

{
    "id": 1,
    "name": "w",
}

What could be the mistake? Or does this validation not work for Jira at all?

4 Likes

Hi @OleksiiSkachkov,

I am facing same issue. May be someone from Atlassian team can help us.

1 Like

I tried to check with the hibernate validator. Added a validator to rest, and now rest method looks like this:

    @POST
    @Produces(APPLICATION_JSON)
    @Consumes({APPLICATION_JSON})
    public Response create(@Valid UserDto userDto) {

        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        
        Validator validator = validatorFactory.usingContext().getValidator();

        Set<ConstraintViolation<@Valid UserDto >> constrains = validator.validate(userDto);
        for (ConstraintViolation constrain : constrains) {

            System.out.println(
                    "[" + constrain.getPropertyPath() + "][" + constrain.getMessage() + "]"
            );
        }

        UserDto result = userService.add(userDto);
        return Response.ok().entity(result).build();
    }

Also, I added to pom dependencies with hibernate validator:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-annotation-processor</artifactId>
            <version>5.2.1.Final</version>
        </dependency>

It works fine. I retrieve in the command line:

But this is just a test. I would not like to use a validator in a situation where I can validate an object field using annotation.

1 Like

Thanks for the solution @OleksiiSkachkov

Hey, @dchouksey89
It’s a shame but this is not a solution. The annotation in the DTO class still doesn’t work. I just checked the validator.
Please uncheck “solution”.

I think this is because Jira (8.x) only includes Jax-RS / JSR-311 in version 1.1.1, but bean validation - if I understand right - is only in there since 2.0.

Maybe it’s possible to integrate it somehow, or to add a servlet filter or interceptor to validate input parameters, but I haven’t tried.

2 Likes

I got this working at least in a basic environment (8.9.0) by adding the following to my pom.xml. What errors are you receiving? In my case, I had many unfound dependencies, which I suppose comes from my usage of * in the <Import-Package> statement.

<dependencies>
    <!-- include javax.validation dependencies -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.2.1.Final</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator-annotation-processor</artifactId>
        <version>5.2.1.Final</version>
        <scope>compile</scope>
    </dependency>
    <!-- end javax.validation dependencies -->
</dependencies>

...

<Import-Package>
    <!-- exclude the javax.validation bits we don't need -->
    !com.thoughtworks.paranamer,
    !javafx.beans.*,
    !javax.money,
    !javax.persistence,
    !org.apache.logging.log4j,
    !org.apache.logging.log4j.*,
    !org.jboss.logmanager,
    !org.jsoup,
    !org.jsoup.*,
    <!-- end customization for javax.validation -->
</Import-Package>

My object is fairly standard:

@JsonRootName("project")
public class Project {
    @JsonProperty
    @NotNull(message = "Cannot be null")
    private Long id;

I receive valid Violations:

validator.validate(project).forEach(violation -> errors.addErrorMessage(violation.getMessage(), 
{
  "errorMessages": [
    "Cannot be null"
  ],
  "errors": {},
  "reasons": [
    "HTTP_400_BAD_REQUEST"
  ]
}

@sfbehnke did you manage to make the Atlassian Spring context validate your beans based solely on the annotations or did you have to wire a validator and perform the call yourself?
From the last line there ([quote=“sfbehnke, post:8, topic:38530”]
validator.validate(project).forEach(violation -> errors.addErrorMessage(violation.getMessage(),
[/quote]) I believe it’s the later. I would be interested if anybody managed to implement the former.

The later only. It’s been years since this post though. I usually roll my own validation handling unfortunately given the lack of support of jax 2.0.

1 Like

supposedly jax2 is coming in platform 7