Skip to content

Commit

Permalink
Upgrade to Jersey 2.28 (#2613)
Browse files Browse the repository at this point in the history
  • Loading branch information
joschi committed Feb 24, 2019
1 parent 528bdb5 commit 8eb57d0
Show file tree
Hide file tree
Showing 83 changed files with 1,028 additions and 705 deletions.
2 changes: 1 addition & 1 deletion docs/source/getting-started.rst
Expand Up @@ -195,7 +195,7 @@ Here's what our configuration class will look like, full `example conf here`_:
import io.dropwizard.Configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;
public class HelloWorldConfiguration extends Configuration {
@NotEmpty
Expand Down
46 changes: 25 additions & 21 deletions docs/source/manual/validation.rst
Expand Up @@ -76,34 +76,37 @@ detailing the validation errors: ``name may not be empty``
class must be marked ``@Valid``. For more information, see the Hibernate Validator documentation
on `Object graphs`_ and `Cascaded validation`_.

.. _Object graphs: https://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/#section-object-graph-validation
.. _Object graphs: https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#section-object-graph-validation

.. _Cascaded validation: https://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/#example-cascaded-validation
.. _Cascaded validation: https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#example-cascaded-validation

Since our entity is also annotated with ``@NotNull``, Dropwizard will also guard against ``null``
input with a response stating that the body must not be null.

.. _man-validation-validations-optional-constraints:

``Optional<T>`` Constraints
***************************
Constraints on optional types
*****************************

If an entity, field, or parameter is not required, it can be wrapped in an ``Optional<T>``, but the
inner value can still be constrained with the ``@UnwrapValidatedValue`` annotation. If the
``Optional`` is absent, then the constraints are not applied.
If an entity, field, or parameter is not strictly required, it can be wrapped in an ``Optional<T>``, but the
wrapped value can still be constrained by setting the annotation parameter ``payload = Unwrapping.Unwrap.class``.
If the optional container is empty, then the constraints are not applied.

Numeric optional types, such as ``OptionalDouble``, ``OptionalInt``, and ``OptionalLong`` do not require explicit
unwrapping.

.. note::

Be careful when using constraints with ``*Param`` annotations on ``Optional<String>`` parameters
Be careful when using constraints with validation annotations on ``Optional<String>`` parameters
as there is a subtle, but important distinction between null and empty. If a client requests
``bar?q=``, ``q`` will evaluate to ``Optional.of("")``. If you want ``q`` to evaluate to
``Optional.absent()`` in this situation, change the type to ``NonEmptyStringParam``
``bar?q=``, the query parameter ``q`` will evaluate to ``Optional.of("")``.
If you want ``q`` to evaluate to ``Optional.empty()`` in this situation, change the type to ``NonEmptyStringParam``.

.. note::

Param types such as ``IntParam`` and ``NonEmptyStringParam`` can also be constrained.
Parameter types such as ``IntParam`` and ``NonEmptyStringParam`` can also be constrained.

There is a caveat regarding ``@UnwrapValidatedValue`` and ``*Param`` types, as there still are some
There is a caveat regarding ``payload = Unwrapping.Unwrap.class`` and ``*Param`` types, as there still are some
cumbersome situations when constraints need to be applied to the container and the value.

.. code-block:: java
Expand All @@ -112,28 +115,29 @@ cumbersome situations when constraints need to be applied to the container and t
// The @NotNull is supposed to mean that the parameter is required but the Max(3) is supposed to
// apply to the contained integer. Currently, this code will fail saying that Max can't
// be applied on an IntParam
public List<Person> createNum(@QueryParam("num") @UnwrapValidatedValue(false)
@NotNull @Max(3) IntParam num) {
public List<Person> createNum(@QueryParam("num")
@NotNull(payload = Unwrapping.Unwrap.class)
@Max(value = 3, payload = Unwrapping.Unwrap.class) IntParam num) {
// ...
}
@GET
// Similarly, the underlying validation framework can't unwrap nested types (an integer wrapped
// in an IntParam wrapped in an Optional), regardless if the @UnwrapValidatedValue is used
// in an IntParam wrapped in an Optional), regardless if `Unwrapping.Unwrap.class` is used
public Person retrieve(@QueryParam("num") @Max(3) Optional<IntParam> num) {
// ...
}
To work around these limitations, if the parameter is required check for it in the endpoint and
throw an exception, else use ``@DefaultValue`` or move the ``Optional`` into the endpoint.
throw an exception, else use ``@DefaultValue`` or move the ``Optional<T>`` into the endpoint.

.. code-block:: java
@POST
// Workaround to handle required int params and validations
public List<Person> createNum(@QueryParam("num") @Max(3) IntParam num) {
if (num == null) {
throw new WebApplicationException("query param num must not be null", 400);
throw new BadRequestException("query param num must not be null");
}
// ...
}
Expand Down Expand Up @@ -312,7 +316,7 @@ Annotations
In addition to the `annotations defined in Hibernate Validator`_, Dropwizard contains another set of annotations,
which are briefly shown below.

.. _annotations defined in Hibernate Validator: https://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/#section-builtin-constraints
.. _annotations defined in Hibernate Validator: https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#section-builtin-constraints

.. code-block:: java
Expand All @@ -325,8 +329,8 @@ which are briefly shown below.
// @OneOf forces a value to value within certain values.
private final String gender;
@Max(10)
@Min(0)
@Min(value = 0, payload = Unwrapping.Unwrap.class)
@Max(value = 10, payload = Unwrapping.Unwrap.class)
// The integer contained, if present, can attain a min value of 0 and a max of 10.
private final Optional<Integer> animals;
Expand Down Expand Up @@ -368,7 +372,7 @@ The ``@Validated`` annotation allows for `validation groups`_ to be specifically
default group. This is useful when different endpoints share the same entity but may have different
validation requirements.

.. _validation groups: https://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/#chapter-groups
.. _validation groups: https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#chapter-groups

Going back to our favorite ``Person`` class. Let's say in the initial version of our API, ``name``
has to be non-empty, but realized that business requirements changed and a name can't be longer than
Expand Down
@@ -1,6 +1,6 @@
package io.dropwizard.auth;

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
Expand Down
@@ -1,7 +1,6 @@
package io.dropwizard.auth;

import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
Expand Down Expand Up @@ -36,13 +35,11 @@ public class PolymorphicAuthValueFactoryProvider<T extends Principal> extends Ab
* {@link Principal} value factory provider injection constructor.
*
* @param mpep multivalued parameter extractor provider
* @param injector injector instance
* @param principalClassSetProvider provider(s) of the principal class
*/
@Inject
public PolymorphicAuthValueFactoryProvider(
MultivaluedParameterExtractorProvider mpep,
ServiceLocator injector,
PrincipalClassSetProvider<T> principalClassSetProvider
) {
super(() -> mpep, Parameter.Source.UNKNOWN);
Expand Down
@@ -1,7 +1,7 @@
package io.dropwizard.auth;

import io.dropwizard.jersey.DropwizardResourceConfig;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
import org.glassfish.jersey.test.TestProperties;

Expand Down
Expand Up @@ -3,7 +3,7 @@
import static org.assertj.core.api.Assertions.assertThat;

import io.dropwizard.auth.principal.NullPrincipal;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.servlet.ServletProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
Expand Down
Expand Up @@ -6,7 +6,7 @@
import io.dropwizard.logging.BootstrapLogging;
import io.dropwizard.util.Maps;
import io.dropwizard.util.Sets;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.servlet.ServletProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
Expand Down
Expand Up @@ -4,7 +4,7 @@
import io.dropwizard.auth.AuthDynamicFeature;
import io.dropwizard.auth.AuthValueFactoryProvider;
import io.dropwizard.logging.BootstrapLogging;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.servlet.ServletProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
Expand Down
Expand Up @@ -9,7 +9,7 @@
import io.dropwizard.logging.BootstrapLogging;
import io.dropwizard.util.Maps;
import io.dropwizard.util.Sets;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.servlet.ServletProperties;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
Expand Down
Expand Up @@ -4,7 +4,7 @@
import io.dropwizard.jersey.validation.Validators;
import io.dropwizard.logging.BootstrapLogging;
import org.glassfish.jersey.server.model.Invocable;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
Expand Down
6 changes: 3 additions & 3 deletions dropwizard-bom/pom.xml
Expand Up @@ -20,7 +20,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<dropwizard.version>${project.version}</dropwizard.version>
<guava.version>27.0.1-jre</guava.version>
<jersey.version>2.27</jersey.version>
<jersey.version>2.28</jersey.version>
<jackson.version>2.9.8</jackson.version>
<jetty.version>9.4.15.v20190215</jetty.version>
<servlet.version>3.0.0.v201112011016</servlet.version>
Expand Down Expand Up @@ -80,9 +80,9 @@
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.3.Final</version>
<version>6.0.14.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
Expand Down
Expand Up @@ -4,7 +4,6 @@
import io.dropwizard.client.proxy.ProxyConfiguration;
import io.dropwizard.client.ssl.TlsConfiguration;
import io.dropwizard.util.Duration;
import org.hibernate.validator.valuehandling.UnwrapValidatedValue;

import javax.annotation.Nullable;
import javax.validation.Valid;
Expand Down Expand Up @@ -49,7 +48,6 @@ public class HttpClientConfiguration {
private int retries = 0;

@NotNull
@UnwrapValidatedValue(false)
private Optional<String> userAgent = Optional.empty();

@Valid
Expand Down
@@ -1,7 +1,7 @@
package io.dropwizard.client.proxy;

import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;

import javax.annotation.Nullable;
import javax.validation.constraints.Pattern;
Expand Down
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.validation.OneOf;
import io.dropwizard.validation.PortRange;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;

import javax.annotation.Nullable;
import javax.validation.Valid;
Expand Down
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.util.Strings;
import io.dropwizard.validation.ValidationMethod;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;

import javax.annotation.Nullable;

Expand Down
Expand Up @@ -37,7 +37,7 @@ public void formatsTheViolationsIntoAHumanReadableMessage() {
assertThat(e.getMessage())
.isEqualTo(String.format(
"config.yml has an error:%n" +
" * woo may not be null%n"
" * woo must not be null%n"
));
}

Expand Down
Expand Up @@ -14,7 +14,7 @@
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Expand Up @@ -11,7 +11,7 @@
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Expand Up @@ -6,12 +6,12 @@
import io.dropwizard.jersey.jackson.JsonProcessingExceptionMapper;
import io.dropwizard.jersey.optional.EmptyOptionalExceptionMapper;
import io.dropwizard.jersey.validation.JerseyViolationExceptionMapper;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;

import javax.ws.rs.ext.ExceptionMapper;

/**
* An HK2 binder that registers all the default exception mappers while allowing users to override
* A binder that registers all the default exception mappers while allowing users to override
* individual exception mappers without disabling all others.
*/
public class ExceptionMapperBinder extends AbstractBinder {
Expand Down
Expand Up @@ -10,14 +10,7 @@
import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
import io.dropwizard.configuration.FileConfigurationSourceProvider;
import io.dropwizard.jackson.Jackson;
import io.dropwizard.jersey.validation.NonEmptyStringParamUnwrapper;
import io.dropwizard.jersey.validation.ParamValidatorUnwrapper;
import io.dropwizard.validation.valuehandling.GuavaOptionalValidatedValueUnwrapper;
import io.dropwizard.validation.valuehandling.OptionalDoubleValidatedValueUnwrapper;
import io.dropwizard.validation.valuehandling.OptionalIntValidatedValueUnwrapper;
import io.dropwizard.validation.valuehandling.OptionalLongValidatedValueUnwrapper;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.internal.engine.ValidatorFactoryImpl;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -100,26 +93,6 @@ public Histogram histogram(String name) {
"jvm.attribute.vendor", "jvm.classloader.loaded", "jvm.filedescriptor");
}

@Test
public void defaultsToDefaultValidatorFactory() throws Exception {
assertThat(bootstrap.getValidatorFactory()).isInstanceOf(ValidatorFactoryImpl.class);

ValidatorFactoryImpl validatorFactory = (ValidatorFactoryImpl) bootstrap.getValidatorFactory();

// It's imperative that the NonEmptyString validator come before the general param validator
// because a NonEmptyString is a param that wraps an optional and the Hibernate Validator
// can't unwrap nested classes it knows how to unwrap.
// https://hibernate.atlassian.net/browse/HV-904
assertThat(validatorFactory.getValidatedValueHandlers())
.extractingResultOf("getClass")
.containsSubsequence(GuavaOptionalValidatedValueUnwrapper.class,
OptionalDoubleValidatedValueUnwrapper.class,
OptionalIntValidatedValueUnwrapper.class,
OptionalLongValidatedValueUnwrapper.class,
NonEmptyStringParamUnwrapper.class,
ParamValidatorUnwrapper.class);
}

@Test
public void canUseCustomValidatorFactory() throws Exception {
ValidatorFactory factory = Validation
Expand Down
Expand Up @@ -15,7 +15,7 @@
import io.dropwizard.validation.BaseValidator;
import org.eclipse.jetty.server.AbstractNetworkConnector;
import org.eclipse.jetty.server.Server;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;
import org.junit.Before;
import org.junit.Test;

Expand Down
Expand Up @@ -5,7 +5,7 @@
import io.dropwizard.jersey.validation.MutableValidatorFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import org.hibernate.validator.internal.constraintvalidators.bv.MinValidatorForNumber;
import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForNumber;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl;
import org.junit.Before;
import org.junit.Test;
Expand Down
Expand Up @@ -7,7 +7,7 @@
import io.dropwizard.validation.MinDuration;
import io.dropwizard.validation.ValidationMethod;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;

import javax.annotation.Nullable;
import javax.validation.constraints.Max;
Expand Down
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotEmpty;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
Expand Down

0 comments on commit 8eb57d0

Please sign in to comment.