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

Introduce LocaleResolver for RESTEasy Reactive #19196

Merged
merged 2 commits into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
import io.quarkus.hibernate.validator.runtime.HibernateValidatorRecorder;
import io.quarkus.hibernate.validator.runtime.ValidatorProvider;
import io.quarkus.hibernate.validator.runtime.interceptor.MethodValidationInterceptor;
import io.quarkus.hibernate.validator.runtime.jaxrs.QuarkusRestViolationExceptionMapper;
import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyConfigSupport;
import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyReactiveViolationExceptionMapper;
import io.quarkus.hibernate.validator.spi.BeanValidationAnnotationsBuildItem;
import io.quarkus.resteasy.common.spi.ResteasyConfigBuildItem;
import io.quarkus.resteasy.common.spi.ResteasyDotNames;
Expand Down Expand Up @@ -153,7 +153,9 @@ void registerAdditionalBeans(HibernateValidatorRecorder hibernateValidatorRecord
} else if (capabilities.isPresent(Capability.RESTEASY_REACTIVE)) {
// The CDI interceptor which will validate the methods annotated with @JaxrsEndPointValidated
additionalBeans.produce(new AdditionalBeanBuildItem(
"io.quarkus.hibernate.validator.runtime.jaxrs.QuarkusRestEndPointValidationInterceptor"));
"io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyReactiveEndPointValidationInterceptor"));
additionalBeans.produce(new AdditionalBeanBuildItem(
"io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyReactiveContextLocaleResolver"));
}

// A constraint validator with an injection point but no scope is added as @Singleton
Expand Down Expand Up @@ -348,7 +350,7 @@ NativeImageConfigBuildItem nativeImageConfig() {

@BuildStep
ExceptionMapperBuildItem mapper() {
return new ExceptionMapperBuildItem(QuarkusRestViolationExceptionMapper.class.getName(),
return new ExceptionMapperBuildItem(ResteasyReactiveViolationExceptionMapper.class.getName(),
ValidationException.class.getName(), Priorities.USER + 1, true);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkus.hibernate.validator.runtime.jaxrs;

import java.util.List;
import java.util.Locale;
import java.util.Optional;

import javax.ws.rs.core.HttpHeaders;

import org.hibernate.validator.spi.messageinterpolation.LocaleResolver;
import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext;

abstract class AbstractLocaleResolver implements LocaleResolver {

protected abstract HttpHeaders getHeaders();

@Override
public Locale resolve(LocaleResolverContext context) {
Optional<List<Locale.LanguageRange>> localePriorities = getAcceptableLanguages();
if (!localePriorities.isPresent()) {
return context.getDefaultLocale();
}

List<Locale> resolvedLocales = Locale.filter(localePriorities.get(), context.getSupportedLocales());
if (resolvedLocales.size() > 0) {
return resolvedLocales.get(0);
}

return context.getDefaultLocale();
}

private Optional<List<Locale.LanguageRange>> getAcceptableLanguages() {
HttpHeaders httpHeaders = getHeaders();
if (httpHeaders != null) {
List<String> acceptLanguageList = httpHeaders.getRequestHeader("Accept-Language");
if (acceptLanguageList != null && !acceptLanguageList.isEmpty()) {
return Optional.of(Locale.LanguageRange.parse(acceptLanguageList.get(0)));
}
}

return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,18 @@
package io.quarkus.hibernate.validator.runtime.jaxrs;

import java.util.List;
import java.util.Locale;
import java.util.Locale.LanguageRange;
import java.util.Optional;

import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;

import org.hibernate.validator.spi.messageinterpolation.LocaleResolver;
import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext;
import org.jboss.resteasy.core.ResteasyContext;

import io.quarkus.arc.DefaultBean;

@Singleton
@DefaultBean
public class ResteasyContextLocaleResolver implements LocaleResolver {
public class ResteasyContextLocaleResolver extends AbstractLocaleResolver {

@Override
public Locale resolve(LocaleResolverContext context) {
Optional<List<LanguageRange>> localePriorities = getAcceptableLanguages();
if (!localePriorities.isPresent()) {
return context.getDefaultLocale();
}

List<Locale> resolvedLocales = Locale.filter(localePriorities.get(), context.getSupportedLocales());
if (resolvedLocales.size() > 0) {
return resolvedLocales.get(0);
}

return context.getDefaultLocale();
protected HttpHeaders getHeaders() {
return ResteasyContext.getContextData(HttpHeaders.class);
}

private Optional<List<LanguageRange>> getAcceptableLanguages() {
HttpHeaders httpHeaders = ResteasyContext.getContextData(HttpHeaders.class);
if (httpHeaders != null) {
List<String> acceptLanguageList = httpHeaders.getRequestHeader("Accept-Language");
if (acceptLanguageList != null && !acceptLanguageList.isEmpty()) {
return Optional.of(LanguageRange.parse(acceptLanguageList.get(0)));
}
}

return Optional.empty();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.hibernate.validator.runtime.jaxrs;

import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;

import io.quarkus.arc.DefaultBean;

@Singleton
@DefaultBean
public class ResteasyReactiveContextLocaleResolver extends AbstractLocaleResolver {

private final HttpHeaders headers;

// automatically injected for RESTEasy Reactive because of org.jboss.resteasy.reactive.server.injection.ContextProducers
public ResteasyReactiveContextLocaleResolver(HttpHeaders headers) {
this.headers = headers;
}

@Override
protected HttpHeaders getHeaders() {
return headers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
@JaxrsEndPointValidated
@Interceptor
@Priority(Interceptor.Priority.PLATFORM_AFTER + 800)
public class QuarkusRestEndPointValidationInterceptor extends AbstractMethodValidationInterceptor {
public class ResteasyReactiveEndPointValidationInterceptor extends AbstractMethodValidationInterceptor {

@AroundInvoke
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import javax.ws.rs.ext.Provider;

@Provider
public class QuarkusRestViolationExceptionMapper implements ExceptionMapper<ValidationException> {
public class ResteasyReactiveViolationExceptionMapper implements ExceptionMapper<ValidationException> {

@Override
public Response toResponse(ValidationException exception) {
Expand Down
2 changes: 1 addition & 1 deletion tcks/resteasy-reactive/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<properties>

<!-- to avoid sudden surprises, checkout is pinned to a specific commit -->
<resteasy-reactive-testsuite.repo.ref>e3cd2c5e5b9262ae5d1197005c542fdd02f9d4ff</resteasy-reactive-testsuite.repo.ref>
<resteasy-reactive-testsuite.repo.ref>8dad67600518d02c8c6b376199efb91d360277b0</resteasy-reactive-testsuite.repo.ref>

<exec.skip>${skipTests}</exec.skip>
<resteasy-reactive-testsuite.clone.skip>${exec.skip}</resteasy-reactive-testsuite.clone.skip>
Expand Down