vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
603 stars 165 forks source link

BeanValidationBinder locale fail in quarkus container #15352

Open Traivor opened 1 year ago

Traivor commented 1 year ago

Description of the bug

When running my application inside a Quarkus container (using their Dockerfile) validation fails with the following stack trace:

2022-12-02 21:24:35,503 ERROR [com.vaa.flo.ser.DefaultErrorHandler] (executor-thread-7) : javax.validation.ValidationException: HV000250: Uninitialized locale: en. Please register your locale as a locale to initialize when initializing your ValidatorFactory.
        at org.hibernate.validator.resourceloading.PlatformResourceBundleLocator.getResourceBundle(PlatformResourceBundleLocator.java:181)
        at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.resolveMessage(AbstractMessageInterpolator.java:449)
        at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.lambda$interpolateMessage$0(AbstractMessageInterpolator.java:399)
        at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330)
        at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.interpolateMessage(AbstractMessageInterpolator.java:399)
        at org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator.interpolate(AbstractMessageInterpolator.java:355)
        at com.vaadin.flow.data.validator.BeanValidator.getMessage(BeanValidator.java:175)
        at com.vaadin.flow.data.validator.BeanValidator.lambda$apply$0(BeanValidator.java:132)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.HashMap$KeySpliterator.tryAdvance(HashMap.java:1728)
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
        at com.vaadin.flow.data.validator.BeanValidator.apply(BeanValidator.java:133)
        at com.vaadin.flow.data.binder.Binder$BindingBuilderImpl.lambda$withValidator$7d13c2a2$1(Binder.java:1053)
        at com.vaadin.flow.data.binder.Binder$ValidatorAsConverter.convertToModel(Binder.java:1604)
        at com.vaadin.flow.data.converter.Converter$2.lambda$convertToModel$6b579330$1(Converter.java:165)
        at com.vaadin.flow.data.binder.SimpleResult.flatMap(SimpleResult.java:65)
        at com.vaadin.flow.data.binder.ValidationResultWrap.flatMap(ValidationResultWrap.java:67)
        at com.vaadin.flow.data.converter.Converter$2.convertToModel(Converter.java:165)
        at com.vaadin.flow.data.binder.Binder$BindingImpl.lambda$doConversion$0(Binder.java:1316)
        at com.vaadin.flow.data.binder.Binder$BindingImpl.execute(Binder.java:1560)
        at com.vaadin.flow.data.binder.Binder$BindingImpl.doConversion(Binder.java:1314)
        at com.vaadin.flow.data.binder.Binder$BindingImpl.doValidation(Binder.java:1334)
        at com.vaadin.flow.data.binder.Binder.lambda$validateBindings$13(Binder.java:2597)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at com.vaadin.flow.data.binder.Binder.validateBindings(Binder.java:2598)
        at com.vaadin.flow.data.binder.Binder.validate(Binder.java:2537)
        at com.vaadin.flow.data.binder.Binder.validate(Binder.java:2517)
        at com.masergy.nms.nom.vaadin.component.NetworkObjectEditor.lambda$init$a8baf231$1(NetworkObjectEditor.java:92)
        at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:233)
        at com.vaadin.flow.component.ComponentEventBus.fireEvent(ComponentEventBus.java:222)
        at com.vaadin.flow.component.Component.fireEvent(Component.java:394)
        at com.vaadin.flow.component.ComponentUtil.fireEvent(ComponentUtil.java:416)
        at com.masergy.nms.nom.vaadin.component.EditDialog.saveClicked(EditDialog.java:60)
        at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:233)
        at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:475)
        at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:292)
        at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:447)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:447)
        at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:62)
        at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:75)
        at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:438)
        at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:419)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:419)
        at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:320)
        at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:115)
        at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
        at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1564)
        at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:369)
        at com.vaadin.quarkus.QuarkusVaadinServlet.service(QuarkusVaadinServlet.java:84)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
        at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
        at com.masergy.nms.nom.servlet.SmallryeRedirect.doFilter(SmallryeRedirect.java:33)
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at com.masergy.nms.nom.servlet.AuthFilter.doFilter(AuthFilter.java:66)
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
        at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
        at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67)
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:56)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1.call(UndertowDeploymentRecorder.java:595)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152)
        at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:120)
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:284)
        at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
        at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$5$1.run(UndertowDeploymentRecorder.java:417)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)

This does NOT happen when using validation either through JPA or by a container managed Validator.

This also does NOT happen when running outside docker. The binder seems to be trying to depend on system level Locales which don't exist inside the container.

Expected behavior

Don't fail due to Locale.

Minimal reproducible example

private final BeanValidationBinder entityBinder = new BeanValidationBinder<>(NetworkObject.class);

entityBinder.setBean(entity);

Versions

melloware commented 1 year ago

I posted on the Dev mailing list to see if its possible: https://groups.google.com/g/quarkus-dev/c/KUHY1q8AfuE