Пользовательский валидатор параметров пути JAX-RS

В настоящее время я экспериментирую с некоторыми RESTful JAX и хочу проверить пользовательский ввод. Обычно регулярное выражение подходит, но мне нужно выполнить более тщательную проверку (~ 10 различных шаблонов регулярных выражений). Я нашел эту страницу при поиске проверки jaxrs. Я заметил, что там написано «Черновик», но решил попробовать.

Я написал свою аннотацию параметра следующим образом:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FooBarValidator.class)
public @interface FooBarParam
{
}

Валидатор выглядит так:

@Provider
public class FooBarValidator
        implements ConstraintValidator<FooBar, Long>
{
    @Override
    public void initialize(FooBar constraintAnnotation)
    {
    }

    @Override
    public boolean isValid(Long value, ConstraintValidatorContext context)
    {
        // validation goes here, this is a test validation
        return (value > 50);
    }
}

Веб-сервис выглядит так:

@javax.ejb.Stateless
@Path("test")
public class testRS
{
    @GET
    @Path("foobar/{fooBar: [0-9]+}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.TEXT_PLAIN)
    public String testService(@FooBar @PathParam("fooBar") Long fooBar)
    {
        return "tested with: " + fooBar;
    }
}

Но если я вызываю свою веб-службу в своем браузере, используя «http://localhost:8080/jaxtest/rest/test/foobar/11», веб-служба вызывается, и мне предоставляется «проверено с: 11». Веб-сервис работает нормально, за исключением того, что валидатор не вызывается.

Я пытался установить точки останова в классе валидатора и интерфейсе аннотаций, но ни одна из них не сработала.

У меня есть подозрение, что я делаю что-то невозможное из-за заголовка «Черновик» в указанной документации. Так что, если я делаю что-то не так или есть альтернативы, я рад это слышать.


person siebz0r    schedule 13.06.2012    source источник
comment
Если вы используете реализацию RestEasy JAX-RS, вы можете легко интегрировать JAX-RS с проверкой компонентов (JSR 303) docs.jboss.org/seam/3/rest/latest/reference/en-US/html/   -  person Piotr Kochański    schedule 15.06.2012


Ответы (2)


Благодаря подсказке @PiotrKochański я успешно реализовал именно то, что хотел. Самая большая проблема заключалась в том, что я обязан использовать Glassfish. По умолчанию Glassfish использует Jersey для работы с JAX.

Мне потребовалось более 10 часов борьбы, чтобы завершить это, так что пусть это сэкономит время всем, кто наткнется на это.

Прежде всего, используйте Maven, это сделает вашу жизнь намного проще.

Второй шаг: добавьте репозиторий JBoss в ваш pom.xml.

<repositories>
    <repository>
        <id>jboss-public-repository-group</id>
        <name>JBoss Public Maven Repository Group</name>
        <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
        <layout>default</layout>
        <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
        </releases>
        <snapshots>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
        </snapshots>
    </repository>
</repositories>

Третий шаг: добавьте зависимости в pom.xml.

<!-- Needed for validator interceptors -->
<dependency>
    <groupId>org.jboss.seam.rest</groupId>
    <artifactId>seam-rest</artifactId>
    <version>3.1.0.Final</version>
</dependency>
<!-- JBoss' RS implementation -->
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>2.3.4.Final</version>
</dependency>
<!-- Because I use JSON I need RESTeasy be able to handle this --> 
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jettison-provider</artifactId>
    <version>2.3.4.Final</version>
</dependency>
<!-- This is THE part that integrates validation in RESTeasy -->
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-hibernatevalidator-provider</artifactId>
    <version>2.3.4.Final</version>
</dependency>

Последняя зависимость заняла у меня довольно много времени. Документы, на которые указал @PiotrKochański не упомянул об этом. Однако в другой версии документов я нашел это:

Интеграция между реализацией API и RESTEasy осуществляется через компонент resteasy-hibernatevalidator-provider. Для интеграции нам нужно добавить resteasy-hibernatevalidator-provider и hibernate-validator в путь к классам. С maven это просто вопрос включения следующей зависимости:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-hibernatevalidator-provider</artifactId>
    <version>2.3-RC1</version>
</dependency>

Четвертым шагом было добавить это в web.xml

<context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
</context-param>
<listener>
    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
    <servlet-name>REST Service</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

Пятым шагом было изменение класса веб-сервиса следующим образом:

@javax.ejb.Stateless
@Path("test")
public class testRS
{
    @GET
    @Path("foobar/{fooBar}")
    @Produces(MediaType.APPLICATION_JSON)
    @org.jboss.resteasy.spi.validation.ValidateRequest
    public String testService(@FooBar @PathParam("fooBar") Long fooBar)
    {
        return "tested with: " + fooBar;
    }
}

Шестым шагом было изменить @interface на это:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FooBarValidator.class)
public @interface FooBarParam
{
    String message() default "{constraint.FooBar}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Также в качестве бонуса; Я наткнулся на презентацию Bean Validation от Эммануэля Бернара и подумал, что могу поделиться, так как она объясняет много интересного.

person siebz0r    schedule 15.06.2012

Страница, которую вы нашли, является одним из предложений о том, что должно войти в JAX-RS 2.0 (что не является окончательным, и это не реализовано). Планируется, что JAX-RS 2.0 будет интегрирован с Bean Validation, но, как я уже сказал, это еще не реализовано.

В настоящее время, если вы хотите проверить ввод, вы можете объявить параметр как String (вместо Long) и выполнить проверку как часть метода ресурса. Затем конвертируйте в Long, если проверка пройдена.

person Martin Matula    schedule 14.06.2012