From 8fb7b060465e5fcd3b3c2b69c94be5a70ac4b5ba Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 10 Oct 2023 11:29:37 +0200 Subject: [PATCH 01/38] Enable disabled TCKs Signed-off-by: Jorge Bescos Gascon --- .../cdi/HelidonContainerImpl.java | 9 +++- .../config/ConfigCdiExtension.java | 3 +- .../HelidonContainerConfiguration.java | 28 +++++++++++- .../HelidonDeployableContainer.java | 25 ++++++----- .../arquillian/HelidonMethodExecutor.java | 7 ++- microprofile/tests/tck/tck-cdi/pom.xml | 28 +++--------- .../tck-cdi/src/test/resources/arquillian.xml | 1 + .../tck-core-profile-test/pom.xml | 8 +--- .../src/test/resources/arquillian.xml | 2 +- microprofile/tests/tck/tck-restful/pom.xml | 2 +- .../tck/tck-restful/tck-restful-test/pom.xml | 44 +------------------ .../src/test/resources/arquillian.xml | 1 + pom.xml | 6 +-- 13 files changed, 73 insertions(+), 91 deletions(-) diff --git a/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonContainerImpl.java b/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonContainerImpl.java index 14d993db4ee..4444c1c6c1d 100644 --- a/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonContainerImpl.java +++ b/microprofile/cdi/src/main/java/io/helidon/microprofile/cdi/HelidonContainerImpl.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; -import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Handler; @@ -46,6 +45,8 @@ import jakarta.enterprise.context.BeforeDestroyed; import jakarta.enterprise.context.Destroyed; import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Startup; +import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.CDI; @@ -96,6 +97,8 @@ final class HelidonContainerImpl extends Weld implements HelidonContainer { private static final Context ROOT_CONTEXT; // whether the current shutdown was invoked by the shutdown hook private static final AtomicBoolean FROM_SHUTDOWN_HOOK = new AtomicBoolean(); + // Default Weld container id. TCKs assumes this value. + private static final String STATIC_INSTANCE = "STATIC_INSTANCE"; static { HelidonFeatures.flavor(HelidonFlavor.MP); @@ -119,7 +122,7 @@ final class HelidonContainerImpl extends Weld implements HelidonContainer { HelidonContainerImpl() { this.bootstrap = new WeldBootstrap(); - id = UUID.randomUUID().toString(); + this.id = STATIC_INSTANCE; } /** @@ -205,6 +208,7 @@ public Collection getResources(String name) { } deployment.getServices().add(ExternalConfiguration.class, configurationBuilder.build()); + // CDI TCK tests expects SE to be excluded, which means Helidon may require to do things that Weld is supposed to do. bootstrap.startContainer(id, Environments.SE, deployment); bootstrap.startInitialization(); @@ -315,6 +319,7 @@ private HelidonContainerImpl doStart() { keepLoggingActive(shutdownHook); bm.getEvent().select(Initialized.Literal.APPLICATION).fire(new ContainerInitialized(id)); + bm.getEvent().select(Any.Literal.INSTANCE).fire(new Startup()); now = System.currentTimeMillis() - now; LOGGER.fine("Container started in " + now + " millis (this excludes the initialization time)"); diff --git a/microprofile/config/src/main/java/io/helidon/microprofile/config/ConfigCdiExtension.java b/microprofile/config/src/main/java/io/helidon/microprofile/config/ConfigCdiExtension.java index 3f1cadb526c..74ed37620b0 100644 --- a/microprofile/config/src/main/java/io/helidon/microprofile/config/ConfigCdiExtension.java +++ b/microprofile/config/src/main/java/io/helidon/microprofile/config/ConfigCdiExtension.java @@ -46,6 +46,7 @@ import jakarta.enterprise.context.Dependent; import jakarta.enterprise.context.spi.CreationalContext; import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.Vetoed; import jakarta.enterprise.inject.spi.AfterBeanDiscovery; import jakarta.enterprise.inject.spi.AfterDeploymentValidation; import jakarta.enterprise.inject.spi.Annotated; @@ -136,7 +137,7 @@ private void processAnnotatedType(@Observes @WithAnnotations(ConfigProperties.cl private void harvestConfigPropertyInjectionPointsFromEnabledObserverMethod(@Observes ProcessObserverMethod event, BeanManager beanManager) { AnnotatedMethod annotatedMethod = event.getAnnotatedMethod(); - if (annotatedMethod != null) { + if (annotatedMethod != null && !annotatedMethod.getDeclaringType().isAnnotationPresent(Vetoed.class)) { List> annotatedParameters = annotatedMethod.getParameters(); if (annotatedParameters != null) { for (AnnotatedParameter annotatedParameter : annotatedParameters) { diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index 54863b4524e..321f09a9fc6 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -36,7 +36,11 @@ * is empty) *
  • replaceConfigSourcesWithMp: (Optional) defaults to false: whether to replace config sources with microprofile if it * exists
  • - *
  • inWebContainer: defaults to false: sets web app context root, load WEB-INF/beans.xml and find any jakarta.ws.rs.core.Application in the webapp classes
  • + *
  • inWebContainer: (Optional) defaults to false: loads WEB-INF/beans.xml and find any + * jakarta.ws.rs.core.Application in the webapp classes
  • + *
  • useBeanXmlTemplate: (Optional) defaults to true: will create the default templates/beans.xml when beans.xml is missing
  • + *
  • includeWarContextPath: (Optional) defaults to false: will include the war name as a root context. + * For example, if a example.war is deployed, the root context is going to be /example.
  • * */ public class HelidonContainerConfiguration implements ContainerConfiguration { @@ -47,6 +51,12 @@ public class HelidonContainerConfiguration implements ContainerConfiguration { private boolean useRelativePath = false; private boolean useParentClassloader = true; private boolean inWebContainer = false; + private boolean useBeanXmlTemplate = true; + /* + * Restful requires it, but core profile don't (because rest used to be deployed in a + * web container together with other apps and in core profile there is only one app) + */ + private boolean includeWarContextPath = false; private final List> builderConsumers = new ArrayList<>(); /** @@ -114,6 +124,22 @@ public void setInWebContainer(boolean inWebContainer) { this.inWebContainer = inWebContainer; } + public boolean isUseBeanXmlTemplate() { + return useBeanXmlTemplate; + } + + public void setUseBeanXmlTemplate(boolean useBeanXmlTemplate) { + this.useBeanXmlTemplate = useBeanXmlTemplate; + } + + public boolean isIncludeWarContextPath() { + return includeWarContextPath; + } + + public void setIncludeWarContextPath(boolean includeWarContextPath) { + this.includeWarContextPath = includeWarContextPath; + } + @Override public void validate() throws ConfigurationException { if ((port <= 0) || (port > Short.MAX_VALUE)) { diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index 36e5185b838..d8aeddfd559 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -90,7 +90,7 @@ *
  • The WebArchive contents are written to the temporary directory
  • *
  • beans.xml is created in WEB-INF/classes if not present
  • *
  • WEB-INF/beans.xml will be moved to WEB-INF/classes/META-INF if present
  • - *
  • The server is started with WEB-INF/classes and all libraries in WEB-INF/libon the classpath.
  • + *
  • The server is started with WEB-INF/classes and all libraries in WEB-INF/lib on the classpath.
  • * * * Control is then returned to the test harness (in this case, generally testng) to run tests over HTTP. @@ -225,7 +225,9 @@ public ProtocolMetaData deploy(Archive archive) throws DeploymentException { ensureBeansXml(classesDir, webInfDir); addServerClasspath(classPath, classesDir, libDir, rootDir); if (containerConfig.isInWebContainer()) { - context.rootContext = archive.getName().split("\\.")[0]; + if (containerConfig.isIncludeWarContextPath()) { + context.rootContext = archive.getName().split("\\.")[0]; + } if (!loadApplicationFromWebXml(context, webInfDir)) { // Search Application in classes loadApplicationFromClasses(context, archive); @@ -341,10 +343,12 @@ static Optional lookForSupressedDeploymentException(Throwable t) { } if (jakarta.enterprise.inject.spi.DeploymentException.class.isAssignableFrom(t.getClass())) { return Optional.of((jakarta.enterprise.inject.spi.DeploymentException) t); - } - if (IllegalStateException.class.isAssignableFrom(t.getClass())) { + } else if (IllegalStateException.class.isAssignableFrom(t.getClass())) { return Optional.of((IllegalStateException) t); + } else if (java.lang.Error.class.isAssignableFrom(t.getClass())) { + return Optional.of((new jakarta.enterprise.inject.spi.DeploymentException(t))); } + var deploymentException = lookForSupressedDeploymentException(t.getCause()); for (Throwable suppressed : t.getSuppressed()) { var candicate = lookForSupressedDeploymentException(suppressed); @@ -519,12 +523,13 @@ private void ensureBeansXml(Path classesDir, Path webinfDir) throws IOException if (Files.exists(beansPath)) { return; } - try (InputStream beanXmlTemplate = HelidonDeployableContainer.class.getResourceAsStream("/templates/beans.xml")) { - if (null == beanXmlTemplate) { - Files.write(beansPath, new byte[0]); - } else { - - Files.copy(beanXmlTemplate, beansPath); + if (containerConfig.isUseBeanXmlTemplate()) { + try (InputStream beanXmlTemplate = HelidonDeployableContainer.class.getResourceAsStream("/templates/beans.xml")) { + if (null == beanXmlTemplate) { + Files.write(beansPath, new byte[0]); + } else { + Files.copy(beanXmlTemplate, beansPath); + } } } } diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonMethodExecutor.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonMethodExecutor.java index 7af711de2a6..619c747e1db 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonMethodExecutor.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonMethodExecutor.java @@ -33,6 +33,7 @@ import io.helidon.microprofile.arquillian.HelidonContainerExtension.HelidonCDIInjectionEnricher; +import jakarta.enterprise.context.ContextNotActiveException; import jakarta.enterprise.context.control.RequestContextController; import org.jboss.arquillian.container.test.spi.ContainerMethodExecutor; import org.jboss.arquillian.test.api.ArquillianResource; @@ -83,7 +84,11 @@ public TestResult invoke(TestMethodExecutor testMethodExecutor) { } catch (Throwable t) { return TestResult.failed(t); } finally { - controller.deactivate(); + try { + controller.deactivate(); + } catch (ContextNotActiveException e) { + LOGGER.log(Level.WARNING, "Controller " + controller + " was already deactivated"); + } } return TestResult.passed(); } diff --git a/microprofile/tests/tck/tck-cdi/pom.xml b/microprofile/tests/tck/tck-cdi/pom.xml index 9b079fe2595..aaf94116b97 100644 --- a/microprofile/tests/tck/tck-cdi/pom.xml +++ b/microprofile/tests/tck/tck-cdi/pom.xml @@ -73,36 +73,22 @@ org.apache.maven.plugins maven-surefire-plugin + + false + 1 false - cdi-full,se + + cdi-full,integration,javaee-full,se jakarta.enterprise:cdi-tck-core-impl - org/jboss/cdi/tck/tests/**/*Test.java - org/jboss/cdi/tck/interceptors/DependentContextTesttests/**/*Test.java + org/jboss/cdi/tck/**/*Test.java - org/jboss/cdi/tck/tests/fulSyntheticBeanWithLookupTestl/extensions/lifecycle/bbd/broken/passivatingScope/AddingPassivatingScopeTest.java - - org/jboss/cdi/tck/tests/build/compatible/extensions/changeObserverQualifier/ChangeObserverQualifierTest.java - org/jboss/cdi/tck/tests/build/compatible/extensions/customStereotype/CustomStereotypeTest.java - org/jboss/cdi/tck/tests/build/compatible/extensions/syntheticBeanWithLookup/SyntheticBeanWithLookupTest.java - org/jboss/cdi/tck/tests/context/dependent/DependentContextTest.java + org/jboss/cdi/tck/tests/definition/bean/types/ManagedBeanTypesTest.java - org/jboss/cdi.tck/tests/event/EventTest.java - org/jboss/cdi/tck/tests/event/lifecycle/StartupShutdownTest.java - org/jboss/cdi/tck/tests/event/observer/broken/validation/unsatisfied/ObserverMethodParameterInjectionValidationTest.java - org/jboss/cdi/tck/tests/event/observer/broken/validation/ambiguous/ObserverMethodParameterInjectionValidationTest.java - org/jboss/cdi/tck/tests/event/observer/runtimeException/ObserverExceptionRethrownTest.java - org/jboss/cdi/tck/tests/event/observer/conditional/ConditionalObserverTest.java - org/jboss/cdi/tck/tests/event/observer/ObserverNotificationTest.java - org/jboss/cdi/tck/tests/event/observer/async/executor/FireAsyncWithCustomExecutorTest.java - org/jboss/cdi/tck/tests/inheritance/generics/MemberLevelInheritanceTest.java - org/jboss/cdi/tck/tests/lookup/clientProxy/unproxyable/privateConstructor/PrivateConstructorTest.java - org/jboss/cdi/tck/tests/lookup/clientProxy/unproxyable/beanConstructor/BeanConstructorWithParametersTest.java - org/jboss/cdi/tck/tests/implementation/simple/lifecycle/unproxyable/UnproxyableManagedBeanTest.java diff --git a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml index 5320417c279..8e8c9ca0132 100644 --- a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml @@ -29,6 +29,7 @@ true + false \ No newline at end of file diff --git a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/pom.xml b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/pom.xml index 0c8fa9bce52..15a2b139640 100644 --- a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/pom.xml +++ b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/pom.xml @@ -33,7 +33,7 @@ io.helidon.microprofile.bundles - helidon-microprofile-core + helidon-microprofile test @@ -77,12 +77,6 @@ *IT.java - - - ee/jakarta/tck/core/jsonb/JsonbApplicationIT.java - ee/jakarta/tck/core/json/ApplicationJsonpIT.java - ee/jakarta/tck/core/rest/jsonb/cdi/CustomJsonbSerializationIT.java - diff --git a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml index f47555c4b3a..2ecdca68d32 100644 --- a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml @@ -27,7 +27,7 @@ - true + true \ No newline at end of file diff --git a/microprofile/tests/tck/tck-restful/pom.xml b/microprofile/tests/tck/tck-restful/pom.xml index 50a2e7f7a0b..28e3c8666b5 100644 --- a/microprofile/tests/tck/tck-restful/pom.xml +++ b/microprofile/tests/tck/tck-restful/pom.xml @@ -48,7 +48,7 @@ - + diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index c6a7472ac76..ca3a4b3509a 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -90,52 +90,10 @@ jakarta.ws.rs:jakarta-restful-ws-tck + xml_binding,servlet,security *IT.java - - - ee/jakarta/tck/ws/rs/ee/rs/core/request/JAXRSClientIT.java - - ee.jakarta.tck.ws.rs.ee.resource.webappexception.mapper.JAXRSClientIT - ee/jakarta/tck/ws/rs/spec/client/exceptions/ClientExceptionsIT.java - ee/jakarta/tck/ws/rs/ee/rs/container/responsecontext/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/pathparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/matrixparam/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/spec/resourceconstructor/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/pathparam/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/beanparam/plain/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/ext/providers/JAXRSProvidersClientIT.java - ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsink/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/spec/provider/sort/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/cookieparam/locator/JAXRSLocatorClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/headerparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/ext/paramconverter/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/beanparam/matrix/plain/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/beanparam/path/plain/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/pathparam/locator/JAXRSLocatorClientIT.java - ee/jakarta/tck/ws/rs/spec/provider/standard/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/signaturetest/jaxrs/JAXRSSigTestIT.java - ee/jakarta/tck/ws/rs/ee/rs/queryparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/jaxrs21/ee/client/executor/rx/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/spec/contextprovider/JsonbContextProviderIT.java - ee/jakarta/tck/ws/rs/spec/resource/locator/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/matrixparam/locator/JAXRSLocatorClientIT.java - ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/ssebroadcaster/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/core/configurable/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/spec/resource/annotationprecedence/subclass/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/sebootstrap/SeBootstrapIT.java - ee/jakarta/tck/ws/rs/ee/rs/core/uriinfo/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/cookieparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/matrixparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/formparam/sub/JAXRSSubClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/formparam/locator/JAXRSLocatorClientIT.java - ee/jakarta/tck/ws/rs/servlet3/rs/applicationpath/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/headerparam/locator/JAXRSLocatorClientIT.java - ee/jakarta/tck/ws/rs/spec/resource/valueofandfromstring/JAXRSClientIT.java - - xml_binding,servlet,security localhost 8080 diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml index a04cc2bee39..a44feb9e4b3 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml @@ -30,6 +30,7 @@ false true + true \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1eaeaa3bf26..6b763be284d 100644 --- a/pom.xml +++ b/pom.xml @@ -61,9 +61,9 @@ 9.1 2.11.0 2.4.14 - 10.0.1 - 4.0.10 - 3.1.3 + 10.0.2 + 4.0.12 + 3.1.4 2.2.1.Final 1.15.3 From 8935601e75289d6a12a8387430c9a290ff0999c0 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 13 Oct 2023 10:15:39 +0200 Subject: [PATCH 02/38] Remove unnecessary HelidonContainerConfiguration property Signed-off-by: Jorge Bescos Gascon --- .../HelidonContainerConfiguration.java | 17 +---------------- .../arquillian/HelidonDeployableContainer.java | 16 +++++++--------- .../tck-cdi/src/test/resources/arquillian.xml | 1 - .../src/test/resources/arquillian.xml | 1 - .../src/test/resources/arquillian.xml | 1 - 5 files changed, 8 insertions(+), 28 deletions(-) diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index 321f09a9fc6..3b116e00cf8 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -36,11 +36,9 @@ * is empty) *
  • replaceConfigSourcesWithMp: (Optional) defaults to false: whether to replace config sources with microprofile if it * exists
  • - *
  • inWebContainer: (Optional) defaults to false: loads WEB-INF/beans.xml and find any - * jakarta.ws.rs.core.Application in the webapp classes
  • *
  • useBeanXmlTemplate: (Optional) defaults to true: will create the default templates/beans.xml when beans.xml is missing
  • *
  • includeWarContextPath: (Optional) defaults to false: will include the war name as a root context. - * For example, if a example.war is deployed, the root context is going to be /example.
  • + * For example, if a example.war is deployed, the root context is going to be /example. Restful TCKs requires this. * */ public class HelidonContainerConfiguration implements ContainerConfiguration { @@ -50,12 +48,7 @@ public class HelidonContainerConfiguration implements ContainerConfiguration { private boolean deleteTmp = true; private boolean useRelativePath = false; private boolean useParentClassloader = true; - private boolean inWebContainer = false; private boolean useBeanXmlTemplate = true; - /* - * Restful requires it, but core profile don't (because rest used to be deployed in a - * web container together with other apps and in core profile there is only one app) - */ private boolean includeWarContextPath = false; private final List> builderConsumers = new ArrayList<>(); @@ -116,14 +109,6 @@ public void setUseParentClassloader(boolean useParentClassloader) { this.useParentClassloader = useParentClassloader; } - public boolean isInWebContainer() { - return inWebContainer; - } - - public void setInWebContainer(boolean inWebContainer) { - this.inWebContainer = inWebContainer; - } - public boolean isUseBeanXmlTemplate() { return useBeanXmlTemplate; } diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index d8aeddfd559..88bc89d4771 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -224,14 +224,12 @@ public ProtocolMetaData deploy(Archive archive) throws DeploymentException { Path libDir = webInfDir.resolve("lib"); ensureBeansXml(classesDir, webInfDir); addServerClasspath(classPath, classesDir, libDir, rootDir); - if (containerConfig.isInWebContainer()) { - if (containerConfig.isIncludeWarContextPath()) { - context.rootContext = archive.getName().split("\\.")[0]; - } - if (!loadApplicationFromWebXml(context, webInfDir)) { - // Search Application in classes - loadApplicationFromClasses(context, archive); - } + if (containerConfig.isIncludeWarContextPath()) { + context.rootContext = archive.getName().split("\\.")[0]; + } + if (!loadApplicationFromWebXml(context, webInfDir)) { + // Search Application in classes + loadApplicationFromClasses(context, archive); } } @@ -512,7 +510,7 @@ private void ensureBeansXml(Path classesDir, Path webinfDir) throws IOException if (null != metaInfPath) { Files.createDirectories(metaInfPath); } - if (containerConfig.isInWebContainer() && webinfDir != null) { + if (webinfDir != null) { // In case exists WEB-INF/beans.xml, then move it to classes/META-INF/beans.xml Path webInfBeansPath = webinfDir.resolve("beans.xml"); if (Files.exists(webInfBeansPath)) { diff --git a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml index 8e8c9ca0132..bbc6d54c166 100644 --- a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml @@ -28,7 +28,6 @@ - true false diff --git a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml index 2ecdca68d32..c3ab26c2322 100644 --- a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml @@ -27,7 +27,6 @@ - true \ No newline at end of file diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml index a44feb9e4b3..02ebe9ededf 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml @@ -29,7 +29,6 @@ false - true true From b9cf14d35c6b1cbbc546b27172aefdaf9632e18f Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 13 Oct 2023 10:40:51 +0200 Subject: [PATCH 03/38] Fixing restfull tcks Signed-off-by: Jorge Bescos Gascon --- .../src/main/java/io/helidon/webserver/http/HttpRouting.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java index 39fabed79fa..c70187eef2e 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/HttpRouting.java @@ -612,7 +612,7 @@ public Void call() throws Exception { return null; } if (result == RoutingResult.NONE) { - throw new NotFoundException("Endpoint not found"); + throw new NotFoundException("Not Found"); } // rerouting, do the more heavyweight while loop @@ -634,7 +634,7 @@ public Void call() throws Exception { response.commit(); return null; } - throw new NotFoundException("Endpoint not found"); + throw new NotFoundException("Not Found"); } private RoutingResult doRoute(ConnectionContext ctx, RoutingRequest request, RoutingResponse response) throws Exception { From 66f114fc121b82e40ee60739938b0da912fff518 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 13 Oct 2023 10:51:32 +0200 Subject: [PATCH 04/38] Revert "Remove unnecessary HelidonContainerConfiguration property" This reverts commit 8935601e75289d6a12a8387430c9a290ff0999c0. Signed-off-by: Jorge Bescos Gascon --- .../HelidonContainerConfiguration.java | 17 ++++++++++++++++- .../arquillian/HelidonDeployableContainer.java | 16 +++++++++------- .../tck-cdi/src/test/resources/arquillian.xml | 1 + .../src/test/resources/arquillian.xml | 1 + .../src/test/resources/arquillian.xml | 1 + 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index 3b116e00cf8..321f09a9fc6 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -36,9 +36,11 @@ * is empty) *
  • replaceConfigSourcesWithMp: (Optional) defaults to false: whether to replace config sources with microprofile if it * exists
  • + *
  • inWebContainer: (Optional) defaults to false: loads WEB-INF/beans.xml and find any + * jakarta.ws.rs.core.Application in the webapp classes
  • *
  • useBeanXmlTemplate: (Optional) defaults to true: will create the default templates/beans.xml when beans.xml is missing
  • *
  • includeWarContextPath: (Optional) defaults to false: will include the war name as a root context. - * For example, if a example.war is deployed, the root context is going to be /example. Restful TCKs requires this.
  • + * For example, if a example.war is deployed, the root context is going to be /example. * */ public class HelidonContainerConfiguration implements ContainerConfiguration { @@ -48,7 +50,12 @@ public class HelidonContainerConfiguration implements ContainerConfiguration { private boolean deleteTmp = true; private boolean useRelativePath = false; private boolean useParentClassloader = true; + private boolean inWebContainer = false; private boolean useBeanXmlTemplate = true; + /* + * Restful requires it, but core profile don't (because rest used to be deployed in a + * web container together with other apps and in core profile there is only one app) + */ private boolean includeWarContextPath = false; private final List> builderConsumers = new ArrayList<>(); @@ -109,6 +116,14 @@ public void setUseParentClassloader(boolean useParentClassloader) { this.useParentClassloader = useParentClassloader; } + public boolean isInWebContainer() { + return inWebContainer; + } + + public void setInWebContainer(boolean inWebContainer) { + this.inWebContainer = inWebContainer; + } + public boolean isUseBeanXmlTemplate() { return useBeanXmlTemplate; } diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index 88bc89d4771..d8aeddfd559 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -224,12 +224,14 @@ public ProtocolMetaData deploy(Archive archive) throws DeploymentException { Path libDir = webInfDir.resolve("lib"); ensureBeansXml(classesDir, webInfDir); addServerClasspath(classPath, classesDir, libDir, rootDir); - if (containerConfig.isIncludeWarContextPath()) { - context.rootContext = archive.getName().split("\\.")[0]; - } - if (!loadApplicationFromWebXml(context, webInfDir)) { - // Search Application in classes - loadApplicationFromClasses(context, archive); + if (containerConfig.isInWebContainer()) { + if (containerConfig.isIncludeWarContextPath()) { + context.rootContext = archive.getName().split("\\.")[0]; + } + if (!loadApplicationFromWebXml(context, webInfDir)) { + // Search Application in classes + loadApplicationFromClasses(context, archive); + } } } @@ -510,7 +512,7 @@ private void ensureBeansXml(Path classesDir, Path webinfDir) throws IOException if (null != metaInfPath) { Files.createDirectories(metaInfPath); } - if (webinfDir != null) { + if (containerConfig.isInWebContainer() && webinfDir != null) { // In case exists WEB-INF/beans.xml, then move it to classes/META-INF/beans.xml Path webInfBeansPath = webinfDir.resolve("beans.xml"); if (Files.exists(webInfBeansPath)) { diff --git a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml index bbc6d54c166..8e8c9ca0132 100644 --- a/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-cdi/src/test/resources/arquillian.xml @@ -28,6 +28,7 @@ + true false diff --git a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml index c3ab26c2322..2ecdca68d32 100644 --- a/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-core-profile/tck-core-profile-test/src/test/resources/arquillian.xml @@ -27,6 +27,7 @@ + true \ No newline at end of file diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml index 02ebe9ededf..a44feb9e4b3 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml @@ -29,6 +29,7 @@ false + true true From 6e7368e186d606ca9be6b00ea35dfc026c8e3c3d Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 16 Oct 2023 15:40:24 +0200 Subject: [PATCH 05/38] Include explicit rest apps Signed-off-by: Jorge Bescos Gascon --- .../arquillian/HelidonDeployableContainer.java | 7 +++++-- .../microprofile/arquillian/ServerRunner.java | 12 ++++++++---- .../tests/tck/tck-restful/tck-restful-test/pom.xml | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index d8aeddfd559..9628ccaaa74 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -308,6 +308,7 @@ private boolean loadApplicationFromWebXml(RunContext context, Path webInfDir) th NodeList childs = nodes.item(i).getChildNodes(); Class application = application(childs); if (application != null) { + context.explicitRsApplication = Optional.of(application); context.applications.add(application); return true; } @@ -442,8 +443,8 @@ void startServer(RunContext context, Path[] classPath) } context.runnerClass - .getDeclaredMethod("start", Config.class, Integer.TYPE) - .invoke(context.runner, config, containerConfig.getPort()); + .getDeclaredMethod("start", Config.class, Integer.TYPE, Optional.class) + .invoke(context.runner, config, containerConfig.getPort(), context.explicitRsApplication); } private URL[] toUrls(Path[] classPath) { @@ -677,6 +678,8 @@ private static class RunContext { // existing class loader private ClassLoader oldClassLoader; private String rootContext; + // It is explicit when it is defined in web.xml. CDI has nothing to do with that. + private Optional> explicitRsApplication = Optional.empty(); private Set> applications = new HashSet<>(); } diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/ServerRunner.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/ServerRunner.java index 17d15c086a0..c17166afcec 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/ServerRunner.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/ServerRunner.java @@ -18,12 +18,14 @@ import java.lang.System.Logger.Level; import java.lang.reflect.Field; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import io.helidon.microprofile.server.Server; import io.helidon.microprofile.server.ServerCdiExtension; import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.spi.ConfigProviderResolver; @@ -56,18 +58,20 @@ private static String getContextRoot(Class application) { * * @param config configuration * @param port port to start the server on + * @param explicitRsApplication defined in web.xml */ - public void start(Config config, int port) { + public void start(Config config, int port, Optional> explicitRsApplication) { // attempt a stop stop(); ConfigProviderResolver.instance() .registerConfig(config, Thread.currentThread().getContextClassLoader()); - server = Server.builder() + Server.Builder builder = Server.builder() .port(port) - .config(config) - .build() + .config(config); + explicitRsApplication.ifPresent(c -> builder.addApplication(c)); + server = builder.build() // this is a blocking operation, we will be released once the server is started // or it fails to start .start(); diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index ca3a4b3509a..5a31281b40d 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -90,7 +90,7 @@ jakarta.ws.rs:jakarta-restful-ws-tck - xml_binding,servlet,security + xml_binding,servlet,security,se_bootstrap *IT.java From 7bfe1e78aabe9218e132df30709c350c236fad8a Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 17 Oct 2023 10:32:33 +0200 Subject: [PATCH 06/38] Defend agains 1+ deployments Signed-off-by: Jorge Bescos Gascon --- .../microprofile/server/EntityMatrixTest.java | 149 +++++++++++++++++ .../JaxRsApplicationMatrixEntityTest.java | 155 ++++++++++++++++++ .../HelidonContainerConfiguration.java | 11 ++ .../HelidonDeployableContainer.java | 122 +++++++------- .../src/test/resources/arquillian.xml | 1 + 5 files changed, 378 insertions(+), 60 deletions(-) create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationMatrixEntityTest.java diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java new file mode 100644 index 00000000000..cba8922ef2f --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +import io.helidon.microprofile.testing.junit5.AddBean; +import io.helidon.microprofile.testing.junit5.HelidonTest; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.MatrixParam; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import org.junit.jupiter.api.Test; + +@HelidonTest +@AddBean(EntityMatrixTest.TestResource.class) +class EntityMatrixTest { + + private static final String FOO = "foo"; + private static final String BAR = "bar"; + + @Test + void defaultValueField(WebTarget target) { + String getResponse = target.path("/field").request().get(String.class); + assertThat(getResponse, is(equalTo(FOO))); + } + + @Test + void customValueField(WebTarget target) { + String getResponse = target.path("/field;matrix=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @Test + void defaultValueParam(WebTarget target) { + String getResponse = target.path("/param").request().get(String.class); + assertThat(getResponse, is(equalTo(FOO))); + } + + @Test + void customValueParam(WebTarget target) { + String getResponse = target.path("/param;matrix=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @Test + void entityMatrix(WebTarget target) { + String getResponse = target.path("/entitymatrix;param=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @Path("/") + @RequestScoped + public static class TestResource { + + @BeanParam + MatrixBeanParamEntity entity; + + @GET + @Path("field") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String field() { + return entity.field.value; + } + + @GET + @Path("param") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String param(@BeanParam MatrixBeanParamEntity entity) { + return entity.field.value; + } + + @GET + @Path("entitymatrix") + public String entitymatrix( + @MatrixParam("param") ParamEntityWithFromStringAndValueOf param) { + return param.getValue(); + } + } + + public static class MatrixBeanParamEntity { + + @DefaultValue(FOO) + @MatrixParam("matrix") + public FieldStr field; + + } + + public static class FieldStr { + + private final String value; + + public FieldStr(String value) { + this.value = value; + } + + } + + public static class ParamEntityWithFromStringAndValueOf { + + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public static ParamEntityWithFromStringAndValueOf valueOf(String arg) { + ParamEntityWithFromStringAndValueOf newEntity = new ParamEntityWithFromStringAndValueOf(); + newEntity.value = arg; + return newEntity; + } + + public static ParamEntityWithFromStringAndValueOf fromString(String arg) { + ParamEntityWithFromStringAndValueOf newEntity = new ParamEntityWithFromStringAndValueOf(); + newEntity.value = arg; + return newEntity; + } + } + +} diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationMatrixEntityTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationMatrixEntityTest.java new file mode 100644 index 00000000000..58a4f8cd680 --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationMatrixEntityTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.MatrixParam; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.MediaType; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class JaxRsApplicationMatrixEntityTest { + + private static final String FOO = "foo"; + private static final String BAR = "bar"; + private static Server server; + private static Client client; + private static int port; + + @BeforeAll + static void beforeAll() { + server = Server.builder().addApplication(MyApplication.class).build(); + server.start(); + port = server.port(); + client = ClientBuilder.newClient(); + } + + @AfterAll + static void afterAll() { + server.stop(); + client.close(); + } + + @Test + void defaultValueField() { + String getResponse = client.target("http://localhost:" + port) + .path("/field").request().get(String.class); + assertThat(getResponse, is(equalTo(FOO))); + } + + @Test + void customValueField() { + String getResponse = client.target("http://localhost:" + port) + .path("/field;matrix=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @Test + void customAndDefaultValueField() { + String getResponse = client.target("http://localhost:" + port) + .path("/field").request().get(String.class); + assertThat(getResponse, is(equalTo(FOO))); + getResponse = client.target("http://localhost:" + port) + .path("/field;matrix=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @Test + void defaultValueParam() { + String getResponse = client.target("http://localhost:" + port) + .path("/param").request().get(String.class); + assertThat(getResponse, is(equalTo(FOO))); + } + + @Test + void customValueParam() { + String getResponse = client.target("http://localhost:" + port) + .path("/param;matrix=" + BAR).request().get(String.class); + assertThat(getResponse, is(equalTo(BAR))); + } + + @ApplicationPath("/") + static class MyApplication extends Application { + + @Override + public java.util.Set> getClasses() { + Set> resources = new HashSet>(); + resources.add(TestResource.class); + return resources; + } + } + + @Path("/") + public static class TestResource { + + @BeanParam + MatrixBeanParamEntity entity; + + @GET + @Path("field") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String field() { + return entity.field.value; + } + + @GET + @Path("param") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String param(@BeanParam MatrixBeanParamEntity entity) { + return entity.field.value; + } + + } + + public static class MatrixBeanParamEntity { + + @DefaultValue(FOO) + @MatrixParam("matrix") + public FieldStr field; + + } + + public static class FieldStr { + + private final String value; + + public FieldStr(String value) { + this.value = value; + } + + } +} diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index 321f09a9fc6..4e8ab201aa8 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -41,6 +41,8 @@ *
  • useBeanXmlTemplate: (Optional) defaults to true: will create the default templates/beans.xml when beans.xml is missing
  • *
  • includeWarContextPath: (Optional) defaults to false: will include the war name as a root context. * For example, if a example.war is deployed, the root context is going to be /example.
  • + *
  • multipleDeployments: (Optional) defaults to true: workaround for tests that unintentionally + * executes 1+ times @org.jboss.arquillian.container.test.api.Deployment
  • * */ public class HelidonContainerConfiguration implements ContainerConfiguration { @@ -52,6 +54,7 @@ public class HelidonContainerConfiguration implements ContainerConfiguration { private boolean useParentClassloader = true; private boolean inWebContainer = false; private boolean useBeanXmlTemplate = true; + private boolean multipleDeployments = true; /* * Restful requires it, but core profile don't (because rest used to be deployed in a * web container together with other apps and in core profile there is only one app) @@ -140,6 +143,14 @@ public void setIncludeWarContextPath(boolean includeWarContextPath) { this.includeWarContextPath = includeWarContextPath; } + public boolean isMultipleDeployments() { + return multipleDeployments; + } + + public void setMultipleDeployments(boolean multipleDeployments) { + this.multipleDeployments = multipleDeployments; + } + @Override public void validate() throws ConfigurationException { if ((port <= 0) || (port > Short.MAX_VALUE)) { diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index 9628ccaaa74..ee94075fecf 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -189,79 +189,81 @@ public ProtocolDescription getDefaultProtocol() { @Override public ProtocolMetaData deploy(Archive archive) throws DeploymentException { - // Because helidon doesn't have a dynamic war deployment model, we need to actually start the server here. - RunContext context = new RunContext(); - contexts.put(archive.getId(), context); + if (containerConfig.isMultipleDeployments() || (!containerConfig.isMultipleDeployments() && contexts.isEmpty())) { + // Because helidon doesn't have a dynamic war deployment model, we need to actually start the server here. + RunContext context = new RunContext(); + contexts.put(archive.getId(), context); - // Is it a JavaArchive? - boolean isJavaArchive = archive instanceof JavaArchive; + // Is it a JavaArchive? + boolean isJavaArchive = archive instanceof JavaArchive; - try { - // Create the temporary deployment directory. - if (containerConfig.getUseRelativePath()) { - context.deployDir = Paths.get("target/helidon-arquillian-test"); - } else { - context.deployDir = Files.createTempDirectory("helidon-arquillian-test"); - } - LOGGER.log(Level.INFO, "Running Arquillian tests in directory: " + context.deployDir.toAbsolutePath()); + try { + // Create the temporary deployment directory. + if (containerConfig.getUseRelativePath()) { + context.deployDir = Paths.get("target/helidon-arquillian-test"); + } else { + context.deployDir = Files.createTempDirectory("helidon-arquillian-test"); + } + LOGGER.log(Level.INFO, "Running Arquillian tests in directory: " + context.deployDir.toAbsolutePath()); - copyArchiveToDeployDir(archive, context.deployDir); + copyArchiveToDeployDir(archive, context.deployDir); - for (Archive additionalArchive : additionalArchives) { - copyArchiveToDeployDir(additionalArchive, context.deployDir); - } + for (Archive additionalArchive : additionalArchives) { + copyArchiveToDeployDir(additionalArchive, context.deployDir); + } - List classPath = new ArrayList<>(); + List classPath = new ArrayList<>(); - Path rootDir = context.deployDir.resolve(""); - if (isJavaArchive) { - ensureBeansXml(rootDir, null); - classPath.add(rootDir); - } else { - // Prepare the launcher files - Path webInfDir = context.deployDir.resolve("WEB-INF"); - Path classesDir = webInfDir.resolve("classes"); - Path libDir = webInfDir.resolve("lib"); - ensureBeansXml(classesDir, webInfDir); - addServerClasspath(classPath, classesDir, libDir, rootDir); - if (containerConfig.isInWebContainer()) { - if (containerConfig.isIncludeWarContextPath()) { - context.rootContext = archive.getName().split("\\.")[0]; - } - if (!loadApplicationFromWebXml(context, webInfDir)) { - // Search Application in classes - loadApplicationFromClasses(context, archive); + Path rootDir = context.deployDir.resolve(""); + if (isJavaArchive) { + ensureBeansXml(rootDir, null); + classPath.add(rootDir); + } else { + // Prepare the launcher files + Path webInfDir = context.deployDir.resolve("WEB-INF"); + Path classesDir = webInfDir.resolve("classes"); + Path libDir = webInfDir.resolve("lib"); + ensureBeansXml(classesDir, webInfDir); + addServerClasspath(classPath, classesDir, libDir, rootDir); + if (containerConfig.isInWebContainer()) { + if (containerConfig.isIncludeWarContextPath()) { + context.rootContext = archive.getName().split("\\.")[0]; + } + if (!loadApplicationFromWebXml(context, webInfDir)) { + // Search Application in classes + loadApplicationFromClasses(context, archive); + } } } - } - startServer(context, classPath.toArray(new Path[0])); - } catch (IOException | SAXException | ParserConfigurationException e) { - LOGGER.log(Level.INFO, "Failed to start container", e); - throw new DeploymentException("Failed to copy the archive assets into the deployment directory", e); - } catch (InvocationTargetException e) { + startServer(context, classPath.toArray(new Path[0])); + } catch (IOException | SAXException | ParserConfigurationException e) { + LOGGER.log(Level.INFO, "Failed to start container", e); + throw new DeploymentException("Failed to copy the archive assets into the deployment directory", e); + } catch (InvocationTargetException e) { - try { - context.runnerClass - .getDeclaredMethod("abortedCleanup") - .invoke(context.runner); - } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) { - ex.printStackTrace(); - } + try { + context.runnerClass + .getDeclaredMethod("abortedCleanup") + .invoke(context.runner); + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) { + ex.printStackTrace(); + } - throw lookForSupressedDeploymentException(e.getTargetException()) - .map(d -> + throw lookForSupressedDeploymentException(e.getTargetException()) + .map(d -> new org.jboss.arquillian.container.spi.client.container.DeploymentException("Deployment failure!", d)) - .orElseThrow(() -> new DefinitionException(e)); - } catch (ReflectiveOperationException e) { - LOGGER.log(Level.INFO, "Failed to start container", e); - throw new DefinitionException(e); // validation exceptions - } + .orElseThrow(() -> new DefinitionException(e)); + } catch (ReflectiveOperationException e) { + LOGGER.log(Level.INFO, "Failed to start container", e); + throw new DefinitionException(e); // validation exceptions + } - // Server has started, so we're done. - // ProtocolMetaData pm = new ProtocolMetaData(); - // pm.addContext(new HTTPContext("Helidon", "localhost", containerConfig.getPort())); - // return pm; + // Server has started, so we're done. + // ProtocolMetaData pm = new ProtocolMetaData(); + // pm.addContext(new HTTPContext("Helidon", "localhost", containerConfig.getPort())); + // return pm; + } return new ProtocolMetaData(); } diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml index a44feb9e4b3..7c1c85c1fba 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml @@ -31,6 +31,7 @@ false true true + false
    \ No newline at end of file From bba4aa7a9389a19ac844680a87a4bdb73eea4b13 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 24 Oct 2023 13:27:35 +0200 Subject: [PATCH 07/38] Fix matrix TCKs Signed-off-by: Jorge Bescos Gascon --- .../uri/src/main/java/io/helidon/common/uri/UriPath.java | 6 ++++++ .../src/main/java/io/helidon/common/uri/UriPathMatrix.java | 5 +++++ .../main/java/io/helidon/common/uri/UriPathNoParam.java | 5 +++++ .../src/test/java/io/helidon/common/uri/UriPathTest.java | 7 +++++++ 4 files changed, 23 insertions(+) diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPath.java b/common/uri/src/main/java/io/helidon/common/uri/UriPath.java index 08a5f5493dc..0aa19f65161 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPath.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPath.java @@ -34,6 +34,12 @@ public interface UriPath { * @return a new path representing the new relative path */ static UriPath createRelative(UriPath uriPath, String relativePath) { + if (uriPath instanceof UriPathMatrix) { + String rawPath = uriPath.rawPath(); + int idx = rawPath.indexOf(relativePath); + rawPath = rawPath.substring(idx); + return new UriPathMatrix(rawPath, relativePath); + } return new UriPathNoParam(uriPath.absolute(), relativePath); } diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java index c19e0eb7c11..e0f18761e09 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java @@ -30,6 +30,11 @@ class UriPathMatrix extends UriPathNoParam { this.rawPath = rawPath; } + UriPathMatrix(String rawPath, String noParamPath, UriPath absolute) { + super(noParamPath, absolute); + this.rawPath = rawPath; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java index 0d4b2d5a2ae..2234c4b2cc7 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java @@ -35,6 +35,11 @@ class UriPathNoParam implements UriPath { this.absolute = this; } + UriPathNoParam(String rawPath, UriPath absolute) { + this.rawPath = rawPath; + this.absolute = absolute; + } + UriPathNoParam(UriPath absolute, String relativePath) { this.rawPath = relativePath; this.decodedPath = relativePath; diff --git a/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java b/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java index f94f70f1193..8f23d3126d6 100644 --- a/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java +++ b/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java @@ -51,4 +51,11 @@ void testDoubleSlash(String rawPath) { UriPath path = UriPath.create(rawPath); assertThat(path.path(), is("/foo/bar")); } + + @Test + void testMatrix() { + UriPath raw = UriPath.create("/jaxrs_spec/resource/entitymatrix;param=ASDFGHJKLQWERTYUIOPPPPPPP"); + UriPath relative = (UriPathMatrix) UriPath.createRelative(raw, "/resource/entitymatrix"); + assertThat(relative.rawPath(), is("/resource/entitymatrix;param=ASDFGHJKLQWERTYUIOPPPPPPP")); + } } From 2cf6c5137715a28d2006a3cd4726efc8f938ecfe Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 25 Oct 2023 15:33:22 +0200 Subject: [PATCH 08/38] Decode path. Fix 1 Signed-off-by: Jorge Bescos Gascon --- .../io/helidon/common/uri/UriPathMatrix.java | 2 +- .../io/helidon/common/uri/UriPathNoParam.java | 7 +- .../java/io/helidon/http/PathMatchers.java | 6 +- .../microprofile/server/JaxRsService.java | 7 + .../server/JaxRsApplicationPathTest.java | 174 ++++++++++++++++++ .../HelidonDeployableContainer.java | 5 + 6 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java index e0f18761e09..1d5025fef88 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java @@ -31,7 +31,7 @@ class UriPathMatrix extends UriPathNoParam { } UriPathMatrix(String rawPath, String noParamPath, UriPath absolute) { - super(noParamPath, absolute); + super(absolute, noParamPath); this.rawPath = rawPath; } diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java index 2234c4b2cc7..178999cb5a1 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java @@ -35,12 +35,9 @@ class UriPathNoParam implements UriPath { this.absolute = this; } - UriPathNoParam(String rawPath, UriPath absolute) { - this.rawPath = rawPath; - this.absolute = absolute; - } - UriPathNoParam(UriPath absolute, String relativePath) { + // relativePath is always decoded, so rawPath will become decoded here. + // This is not really the meaning of rawPath. this.rawPath = relativePath; this.decodedPath = relativePath; this.absolute = absolute; diff --git a/http/http/src/main/java/io/helidon/http/PathMatchers.java b/http/http/src/main/java/io/helidon/http/PathMatchers.java index 9aa0eff66d4..bbaaff18a86 100644 --- a/http/http/src/main/java/io/helidon/http/PathMatchers.java +++ b/http/http/src/main/java/io/helidon/http/PathMatchers.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; import io.helidon.common.parameters.Parameters; +import io.helidon.common.uri.UriEncoding; import io.helidon.common.uri.UriPath; /** @@ -276,8 +277,9 @@ static final class ExactPathMatcher implements PathMatcher { private final String pathWithTrailingSlash; ExactPathMatcher(String path) { - this.path = path; - this.pathWithTrailingSlash = path + "/"; + // We work with decoded URIs + this.path = UriEncoding.decodeUri(path); + this.pathWithTrailingSlash = this.path + "/"; } @Override diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java index 159bbf5b583..7d4e6a74325 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java @@ -204,6 +204,13 @@ private void doHandle(Context ctx, ServerRequest req, ServerResponse res) { String rawPath = req.path().rawPath(); rawPath = rawPath.startsWith("/") ? rawPath.substring(1) : rawPath; + /* + * rawPath could be a decoded path here because of UriPathNoParam(41). + * Paths generated from decoded URIs could contain whitespace, + * and URIs cannot be created with whitespace (it throws one IllegalException). + * I didn't find a better solution than the next. + */ + rawPath = rawPath.replaceAll(" ", "%20"); if (req.query().isEmpty()) { requestUri = baseUri.resolve(rawPath); } else { diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java new file mode 100644 index 00000000000..330ee2875b8 --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.Encoded; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.UriInfo; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +class JaxRsApplicationPathTest { + + private static Server server; + private static Client client; + private static int port; + + @BeforeAll + static void beforeAll() { + server = Server.builder().addApplication(MyApplication.class).build(); + server.start(); + port = server.port(); + client = ClientBuilder.newClient(); + } + + @AfterAll + static void afterAll() { + server.stop(); + client.close(); + } + + @Test + void okTest() { + String getResponse = client.target("http://localhost:" + port) + .path("/ApplicationPath!/Resource").request().get(String.class); + assertThat(getResponse, is("ok")); + } + + @Test + void nokTest() { + int status = client.target("http://localhost:" + port) + .path("/Resource").request().get().getStatus(); + assertThat(status, is(404)); + } + + @Test + void emptyParamTest() { + String getResponse = client.target("http://localhost:" + port) + .path("/ApplicationPath!/Resource/pathparam1/%20/%2010").request().get(String.class); + assertThat(getResponse, is("a= b= 10")); + } + + @Test + public void testEncoded() { + String getResponse = client.target("http://localhost:" + port) + .path("/ApplicationPath!/Resource/encoded").queryParam("query", "%dummy23+a") + .request().get(String.class); + assertThat(getResponse, is("true:%25dummy23%2Ba")); + } + + @Test + public void testDecoded() { + String getResponse = client.target("http://localhost:" + port) + .path("/ApplicationPath!/Resource/decoded").queryParam("query", "%dummy23+a") + .request().get(String.class); + assertThat(getResponse, is("true:%dummy23+a")); + } + + @Test + @Disabled("Enable to investigate TCK issue") + void encodedEntityTest() { + String getResponse = client.target("http://localhost:" + port) + .path("/ApplicationPath!/Resource/ParamEntityWithFromString/test%21/test!/test!/test%21") + .request().get(String.class); + assertThat(getResponse, is("test%21test!test%21test!")); + } + + @ApplicationPath("/ApplicationPath%21") + static class MyApplication extends Application { + + @Override + public java.util.Set> getClasses() { + Set> resources = new HashSet>(); + resources.add(TestResource.class); + return resources; + } + } + + @Path("/Resource") + public static class TestResource { + + @GET + public String param() { + return "ok"; + } + + @GET + @Path("/pathparam1/{a}/{b}") + public String pathparamTest1(@Context UriInfo info) { + StringBuilder buf = new StringBuilder(); + for (String param : info.getPathParameters(true).keySet()) { + buf.append(param + "=" + info.getPathParameters(true).getFirst(param)); + } + return buf.toString(); + } + + @GET + @Path("/ParamEntityWithFromString/{encoded}/{notEncoded}/{encoded2}/{notEncoded2}") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String stringParamHandlingFromString( + @BeanParam PathBeanParamEntity bean) { + return bean.encoded + bean.notEncoded + bean.encoded2 + bean.notEncoded2; + } + + @GET + @Path("encoded") + public String getEncoded(@Encoded @QueryParam("query") String queryParam) { + return queryParam.equals("%25dummy23%2Ba") + ":" + queryParam; + } + + @GET + @Path("decoded") + public String getDecoded(@QueryParam("query") String queryParam) { + return queryParam.equals("%dummy23+a") + ":" + queryParam; + } + } + + static class PathBeanParamEntity { + @Encoded + @PathParam("encoded") + public String encoded; + @PathParam("notEncoded") + public String notEncoded; + @Encoded + @PathParam("encoded2") + public String encoded2; + @PathParam("notEncoded2") + public String notEncoded2; + } +} diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index ee94075fecf..25c2732d115 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -58,6 +58,7 @@ import jakarta.enterprise.inject.spi.CDI; import jakarta.enterprise.inject.spi.DefinitionException; import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; @@ -417,7 +418,11 @@ void startServer(RunContext context, Path[] classPath) Map properties = new HashMap<>(); for (Class app : context.applications) { String key = app.getName() + ".routing-path.path"; + ApplicationPath path = app.getDeclaredAnnotation(ApplicationPath.class); String value = "/" + context.rootContext; + if (path != null && !"/".equals(path.value())) { + value = value + "/" + path.value(); + } properties.put(key, value); } configBuilder.withSources(MpConfigSources.create(properties)); From 6921bce873d4faafdbfa27e5fecf3f985a3969af Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 14 Nov 2023 14:31:30 +0100 Subject: [PATCH 09/38] Fix encoded paths Signed-off-by: Jorge Bescos Gascon --- .../java/io/helidon/common/uri/UriPath.java | 6 -- .../io/helidon/common/uri/UriPathMatrix.java | 5 -- .../io/helidon/common/uri/UriPathNoParam.java | 2 - .../io/helidon/common/uri/UriPathTest.java | 7 --- .../microprofile/server/JaxRsService.java | 57 +++++++++---------- .../server/JaxRsApplicationPathTest.java | 3 +- 6 files changed, 28 insertions(+), 52 deletions(-) diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPath.java b/common/uri/src/main/java/io/helidon/common/uri/UriPath.java index 0aa19f65161..08a5f5493dc 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPath.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPath.java @@ -34,12 +34,6 @@ public interface UriPath { * @return a new path representing the new relative path */ static UriPath createRelative(UriPath uriPath, String relativePath) { - if (uriPath instanceof UriPathMatrix) { - String rawPath = uriPath.rawPath(); - int idx = rawPath.indexOf(relativePath); - rawPath = rawPath.substring(idx); - return new UriPathMatrix(rawPath, relativePath); - } return new UriPathNoParam(uriPath.absolute(), relativePath); } diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java index 1d5025fef88..c19e0eb7c11 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathMatrix.java @@ -30,11 +30,6 @@ class UriPathMatrix extends UriPathNoParam { this.rawPath = rawPath; } - UriPathMatrix(String rawPath, String noParamPath, UriPath absolute) { - super(absolute, noParamPath); - this.rawPath = rawPath; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java index 178999cb5a1..0d4b2d5a2ae 100644 --- a/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java +++ b/common/uri/src/main/java/io/helidon/common/uri/UriPathNoParam.java @@ -36,8 +36,6 @@ class UriPathNoParam implements UriPath { } UriPathNoParam(UriPath absolute, String relativePath) { - // relativePath is always decoded, so rawPath will become decoded here. - // This is not really the meaning of rawPath. this.rawPath = relativePath; this.decodedPath = relativePath; this.absolute = absolute; diff --git a/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java b/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java index 8f23d3126d6..f94f70f1193 100644 --- a/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java +++ b/common/uri/src/test/java/io/helidon/common/uri/UriPathTest.java @@ -51,11 +51,4 @@ void testDoubleSlash(String rawPath) { UriPath path = UriPath.create(rawPath); assertThat(path.path(), is("/foo/bar")); } - - @Test - void testMatrix() { - UriPath raw = UriPath.create("/jaxrs_spec/resource/entitymatrix;param=ASDFGHJKLQWERTYUIOPPPPPPP"); - UriPath relative = (UriPathMatrix) UriPath.createRelative(raw, "/resource/entitymatrix"); - assertThat(relative.rawPath(), is("/resource/entitymatrix;param=ASDFGHJKLQWERTYUIOPPPPPPP")); - } } diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java index 7d4e6a74325..8f717087a2b 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java @@ -121,7 +121,7 @@ static JaxRsService create(ResourceConfig resourceConfig, InjectionManager injec return new JaxRsService(resourceConfig, appHandler, container); } - static String basePath(UriPath path) { + private static String basePath(UriPath path) { String reqPath = path.path(); String absPath = path.absolute().path(); String basePath = absPath.substring(0, absPath.length() - reqPath.length() + 1); @@ -179,14 +179,6 @@ private static Application getApplication(ResourceConfig resourceConfig) { return application; } - private static URI baseUri(ServerRequest req) { - String uri = (req.isSecure() ? "https" : "http") - + "://" + req.authority() - + basePath(req.path()); - - return URI.create(uri); - } - private void handle(ServerRequest req, ServerResponse res) { Context context = req.context(); @@ -197,28 +189,11 @@ private void handle(ServerRequest req, ServerResponse res) { // call doHandle in active context Contexts.runInContext(context, () -> doHandle(context, req, res)); } - + private void doHandle(Context ctx, ServerRequest req, ServerResponse res) { - URI baseUri = baseUri(req); - URI requestUri; - - String rawPath = req.path().rawPath(); - rawPath = rawPath.startsWith("/") ? rawPath.substring(1) : rawPath; - /* - * rawPath could be a decoded path here because of UriPathNoParam(41). - * Paths generated from decoded URIs could contain whitespace, - * and URIs cannot be created with whitespace (it throws one IllegalException). - * I didn't find a better solution than the next. - */ - rawPath = rawPath.replaceAll(" ", "%20"); - if (req.query().isEmpty()) { - requestUri = baseUri.resolve(rawPath); - } else { - requestUri = baseUri.resolve(rawPath + "?" + req.query().rawValue()); - } - - ContainerRequest requestContext = new ContainerRequest(baseUri, - requestUri, + BaseUriRequestUri uris = BaseUriRequestUri.resolve(req); + ContainerRequest requestContext = new ContainerRequest(uris.baseUri, + uris.requestUri, req.prologue().method().text(), new HelidonMpSecurityContext(), new MapPropertiesDelegate(), resourceConfig); @@ -452,4 +427,26 @@ public void write(int b) throws IOException { delegate.write(b); } } + + private static class BaseUriRequestUri { + private final URI baseUri; + private final URI requestUri; + + private BaseUriRequestUri(URI baseUri, URI requestUri) { + this.baseUri = baseUri; + this.requestUri = requestUri; + } + + private static BaseUriRequestUri resolve(ServerRequest req) { + String processedBasePath = basePath(req.path()); + String rawPath = req.path().absolute().rawPath(); + String prefix = (req.isSecure() ? "https" : "http") + "://" + req.authority(); + String serverBasePath = prefix + processedBasePath; + String requestPath = prefix + rawPath; + if (!req.query().isEmpty()) { + requestPath = requestPath + "?" + req.query().rawValue(); + } + return new BaseUriRequestUri(URI.create(serverBasePath), URI.create(requestPath)); + } + } } diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java index 330ee2875b8..523b596d162 100644 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationPathTest.java @@ -100,12 +100,11 @@ public void testDecoded() { } @Test - @Disabled("Enable to investigate TCK issue") void encodedEntityTest() { String getResponse = client.target("http://localhost:" + port) .path("/ApplicationPath!/Resource/ParamEntityWithFromString/test%21/test!/test!/test%21") .request().get(String.class); - assertThat(getResponse, is("test%21test!test%21test!")); + assertThat(getResponse, is("test%21test!test!test!")); } @ApplicationPath("/ApplicationPath%21") From e8d23e3c0014d4071c762b337108f0ef27ee847b Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 14 Nov 2023 15:46:30 +0100 Subject: [PATCH 10/38] Exclude some root context paths Signed-off-by: Jorge Bescos Gascon --- .../arquillian/HelidonContainerConfiguration.java | 13 +++++++++++++ .../arquillian/HelidonDeployableContainer.java | 7 +++++-- .../src/test/resources/arquillian.xml | 2 ++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index 4e8ab201aa8..e59dccdef3b 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -17,7 +17,10 @@ package io.helidon.microprofile.arquillian; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Consumer; import org.eclipse.microprofile.config.spi.ConfigBuilder; @@ -41,6 +44,7 @@ *
  • useBeanXmlTemplate: (Optional) defaults to true: will create the default templates/beans.xml when beans.xml is missing
  • *
  • includeWarContextPath: (Optional) defaults to false: will include the war name as a root context. * For example, if a example.war is deployed, the root context is going to be /example.
  • + *
  • skipContextPaths: (Optional) defaults to empty: define the context paths to be excluded.
  • *
  • multipleDeployments: (Optional) defaults to true: workaround for tests that unintentionally * executes 1+ times @org.jboss.arquillian.container.test.api.Deployment
  • * @@ -61,6 +65,7 @@ public class HelidonContainerConfiguration implements ContainerConfiguration { */ private boolean includeWarContextPath = false; private final List> builderConsumers = new ArrayList<>(); + private final Set skipContextPaths = new HashSet<>(); /** * Access container's config builder. @@ -166,4 +171,12 @@ ConfigBuilder useBuilder(ConfigBuilder configBuilder) { this.builderConsumers.forEach(builderConsumer -> builderConsumer.accept(configBuilder)); return configBuilder; } + + public Set getSkipContextPaths() { + return skipContextPaths; + } + + public void setSkipContextPaths(String skipContextPaths) { + this.skipContextPaths.addAll(Arrays.asList(skipContextPaths.trim().split(","))); + } } diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java index 25c2732d115..1d58a944a34 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonDeployableContainer.java @@ -228,7 +228,10 @@ public ProtocolMetaData deploy(Archive archive) throws DeploymentException { addServerClasspath(classPath, classesDir, libDir, rootDir); if (containerConfig.isInWebContainer()) { if (containerConfig.isIncludeWarContextPath()) { - context.rootContext = archive.getName().split("\\.")[0]; + String rootContext = archive.getName().split("\\.")[0]; + if (!containerConfig.getSkipContextPaths().contains(rootContext)) { + context.rootContext = rootContext; + } } if (!loadApplicationFromWebXml(context, webInfDir)) { // Search Application in classes @@ -420,7 +423,7 @@ void startServer(RunContext context, Path[] classPath) String key = app.getName() + ".routing-path.path"; ApplicationPath path = app.getDeclaredAnnotation(ApplicationPath.class); String value = "/" + context.rootContext; - if (path != null && !"/".equals(path.value())) { + if (path != null && !"/".equals(path.value()) && !"".equals(path.value())) { value = value + "/" + path.value(); } properties.put(key, value); diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml index 7c1c85c1fba..023f94713f6 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/arquillian.xml @@ -30,7 +30,9 @@ false true + true + jaxrs_contextprovider_jsonb_web,jaxrs_client_exceptions false From d5b1ff63e2b0e6e8c9b792989dd3ae4ab874100a Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 14 Nov 2023 15:54:45 +0100 Subject: [PATCH 11/38] Check style Signed-off-by: Jorge Bescos Gascon --- .../java/io/helidon/microprofile/server/JaxRsService.java | 2 +- .../arquillian/HelidonContainerConfiguration.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java index 8f717087a2b..1dee9e2b106 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java @@ -189,7 +189,7 @@ private void handle(ServerRequest req, ServerResponse res) { // call doHandle in active context Contexts.runInContext(context, () -> doHandle(context, req, res)); } - + private void doHandle(Context ctx, ServerRequest req, ServerResponse res) { BaseUriRequestUri uris = BaseUriRequestUri.resolve(req); ContainerRequest requestContext = new ContainerRequest(uris.baseUri, diff --git a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java index e59dccdef3b..176eb0b6a2b 100644 --- a/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java +++ b/microprofile/tests/arquillian/src/main/java/io/helidon/microprofile/arquillian/HelidonContainerConfiguration.java @@ -172,10 +172,18 @@ ConfigBuilder useBuilder(ConfigBuilder configBuilder) { return configBuilder; } + /** + * Getter of skipContextPaths. + * @return the skipContextPaths + */ public Set getSkipContextPaths() { return skipContextPaths; } + /** + * List of comma separated context roots that should be excluded. + * @param skipContextPaths the context paths + */ public void setSkipContextPaths(String skipContextPaths) { this.skipContextPaths.addAll(Arrays.asList(skipContextPaths.trim().split(","))); } From 0f46502451983f3d2c86a21ffe8d5172bc24086b Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 15 Nov 2023 07:54:05 +0100 Subject: [PATCH 12/38] JAXRSProvidersClientIT fix Signed-off-by: Jorge Bescos Gascon --- .../io/helidon/microprofile/server/JaxRsCdiExtension.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java index 1cb1cbe845e..31db37319bd 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java @@ -283,13 +283,15 @@ JaxRsService toJerseySupport(JaxRsApplication jaxRsApplication, injectionManager); } + // @Priority does not have any effect. This should map to Exception, + // but it is invoked before user ExceptionMapper. This probably requires an issue. @Provider - private static class CatchAllExceptionMapper implements ExceptionMapper { + private static class CatchAllExceptionMapper implements ExceptionMapper { @Context private ServerRequest serverRequest; @Override - public Response toResponse(Exception exception) { + public Response toResponse(Throwable exception) { serverRequest.context().register("unmappedException", exception); if (exception instanceof WebApplicationException wae) { return wae.getResponse(); From 45599b334244791e4166183b3639439e0cc7017a Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 15 Nov 2023 08:55:40 +0100 Subject: [PATCH 13/38] Fix JAXRSSigTestIT Signed-off-by: Jorge Bescos Gascon --- .../tck/tck-restful/tck-restful-test/pom.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 5a31281b40d..ba9acad5bed 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -81,6 +81,20 @@ true + + maven-dependency-plugin + + + compile + + copy-dependencies + + + ${project.build.directory}/lib + + + + org.apache.maven.plugins maven-surefire-plugin @@ -97,6 +111,8 @@ localhost 8080 + ${project.build.directory}/jdk11-bundle + ${project.build.directory}/lib/jakarta.xml.bind-api-${version.lib.jakarta.xml.bind-api}.jar:${project.build.directory}/lib/jakarta.ws.rs-api-${version.lib.jakarta.jaxrs-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming From dcf0cfb29438070fce658f9783363d3507499291 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 15 Nov 2023 11:11:24 +0100 Subject: [PATCH 14/38] Working in JaxRsApplicationVisibilityTest Signed-off-by: Jorge Bescos Gascon --- microprofile/server/pom.xml | 5 + .../JaxRsApplicationVisibilityTest.java | 140 ++++++++++++++++++ .../tck/tck-restful/tck-restful-test/pom.xml | 1 + .../src/test/resources/META-INF/beans.xml | 25 ++++ 4 files changed, 171 insertions(+) create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java create mode 100644 microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml diff --git a/microprofile/server/pom.xml b/microprofile/server/pom.xml index 408898c8df8..49837f9c53b 100644 --- a/microprofile/server/pom.xml +++ b/microprofile/server/pom.xml @@ -31,6 +31,11 @@ Helidon Microprofile Server Server of the microprofile implementation + + -Xmx1024m -Dfile.encoding=UTF-8 -Dorg.jboss.weld.construction.relaxed=false + -Xmx1024m -Dfile.encoding=UTF-8 -Dorg.jboss.weld.construction.relaxed=false + + io.helidon.config diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java new file mode 100644 index 00000000000..be2092774aa --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Request; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.UriInfo; +import jakarta.ws.rs.ext.Providers; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +class JaxRsApplicationVisibilityTest { + + private static Server server; + private static Client client; + private static int port; + + @BeforeAll + static void beforeAll() { + server = Server.builder().addApplication(MyApplication.class).build(); + server.start(); + port = server.port(); + client = ClientBuilder.newClient(); + } + + @AfterAll + static void afterAll() { + server.stop(); + client.close(); + } + + @Disabled("Failing, it is invoking the empty Resource constructor") + @Test + void okTest() { + Response response = client.target("http://localhost:" + port).path("/Application/Resource/mostAttributes") + .request().get(); + assertThat(response.getStatus(), is(Status.OK.getStatusCode())); + } + + @ApplicationPath("/Application") + static class MyApplication extends Application { + + @Override + public java.util.Set> getClasses() { + Set> resources = new HashSet>(); + resources.add(Resource.class); + return resources; + } + } + + @Path("/Resource") + public static class Resource { + + private HttpHeaders headers; + private UriInfo info; + private Application application; + private Request request; + private Providers provider; + + public Resource() { + } + + public Resource(@Context HttpHeaders headers) { + this.headers = headers; + } + + public Resource(@Context HttpHeaders headers, @Context UriInfo info) { + this.headers = headers; + this.info = info; + } + + public Resource(@Context HttpHeaders headers, @Context UriInfo info, + @Context Application application) { + this.application = application; + this.headers = headers; + this.info = info; + } + + public Resource(@Context HttpHeaders headers, @Context UriInfo info, + @Context Application application, @Context Request request) { + this.application = application; + this.headers = headers; + this.info = info; + this.request = request; + } + + protected Resource(@Context HttpHeaders headers, @Context UriInfo info, + @Context Application application, @Context Request request, + @Context Providers provider) { + this.application = application; + this.headers = headers; + this.info = info; + this.request = request; + this.provider = provider; + } + + @GET + @Path("mostAttributes") + public Response isUsedConstructorWithMostAttributes() { + boolean ok = application != null; + ok &= headers != null; + ok &= info != null; + ok &= request != null; + ok &= provider == null; + Status status = ok ? Status.OK : Status.NOT_ACCEPTABLE; + return Response.status(status).build(); + } + } +} diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index ba9acad5bed..4b6882cde8f 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -111,6 +111,7 @@ localhost 8080 + false ${project.build.directory}/jdk11-bundle ${project.build.directory}/lib/jakarta.xml.bind-api-${version.lib.jakarta.xml.bind-api}.jar:${project.build.directory}/lib/jakarta.ws.rs-api-${version.lib.jakarta.jaxrs-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml new file mode 100644 index 00000000000..0b4e9309231 --- /dev/null +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + From 96f77621123908512095aff189461121122c9195 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 20 Nov 2023 09:46:21 +0100 Subject: [PATCH 15/38] Remove bundle from pom Signed-off-by: Jorge Bescos Gascon --- .../microprofile/server/JaxRsCdiExtension.java | 4 ++-- .../tck/tck-restful/tck-restful-test/pom.xml | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java index 31db37319bd..0d2e37de214 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java @@ -283,8 +283,8 @@ JaxRsService toJerseySupport(JaxRsApplication jaxRsApplication, injectionManager); } - // @Priority does not have any effect. This should map to Exception, - // but it is invoked before user ExceptionMapper. This probably requires an issue. + // Throwable as temporal fix to pass TCKs meanwhile + // https://github.com/eclipse-ee4j/jersey/pull/5469 is not released @Provider private static class CatchAllExceptionMapper implements ExceptionMapper { @Context diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 4b6882cde8f..37224416568 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -59,10 +59,23 @@ test - io.helidon.microprofile.bundles - helidon-microprofile + io.helidon.microprofile.server + helidon-microprofile-server test + + io.helidon.microprofile.rest-client + helidon-microprofile-rest-client + + + org.glassfish.jersey.media + jersey-media-json-binding + runtime + + + jakarta.json.bind + jakarta.json.bind-api + com.sun.xml.bind jaxb-impl From 3e1c47b87e1f394b8a0b3e254f4edd3c3ef22181 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 20 Nov 2023 14:30:35 +0100 Subject: [PATCH 16/38] Fix Datasource tests Signed-off-by: Jorge Bescos Gascon --- .../java/io/helidon/microprofile/server/JaxRsService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java index 1dee9e2b106..8f3fccee798 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java @@ -69,9 +69,6 @@ import org.glassfish.jersey.server.spi.Container; import org.glassfish.jersey.server.spi.ContainerResponseWriter; -import static org.glassfish.jersey.CommonProperties.PROVIDER_DEFAULT_DISABLE; -import static org.glassfish.jersey.server.ServerProperties.WADL_FEATURE_DISABLE; - class JaxRsService implements HttpService { /** * If set to {@code "true"}, Jersey will ignore responses in exceptions. @@ -98,8 +95,6 @@ private JaxRsService(ResourceConfig resourceConfig, } static JaxRsService create(ResourceConfig resourceConfig, InjectionManager injectionManager) { - resourceConfig.property(PROVIDER_DEFAULT_DISABLE, "ALL"); - resourceConfig.property(WADL_FEATURE_DISABLE, "true"); InjectionManager ij = injectionManager == null ? null : new InjectionManagerWrapper(injectionManager, resourceConfig); ApplicationHandler appHandler = new ApplicationHandler(resourceConfig, From 3096765ead92fc7195367e045930de121c510f22 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 21 Nov 2023 12:25:47 +0100 Subject: [PATCH 17/38] Add JaxRsApplicationOrderFiltersTest Signed-off-by: Jorge Bescos Gascon --- .../JaxRsApplicationOrderFiltersTest.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationOrderFiltersTest.java diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationOrderFiltersTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationOrderFiltersTest.java new file mode 100644 index 00000000000..c96d858ef5c --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationOrderFiltersTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.Provider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class JaxRsApplicationOrderFiltersTest { + + private static Server server; + private static Client client; + private static int port; + + @BeforeAll + static void beforeAll() { + server = Server.builder().addApplication(MyApplication.class).build(); + server.start(); + port = server.port(); + client = ClientBuilder.newClient(); + } + + @AfterAll + static void afterAll() { + server.stop(); + client.close(); + } + + @Test + void changeOrderTest() { + Response response = client.target("http://localhost:" + port) + .path("/echo").register(SecondFilter.class, 100) + .register(FirstFilter.class, 200) + .request().post(Entity.text("test")); + assertThat(response.readEntity(String.class), is(FirstFilter.class.getName())); + } + + @Test + void priorityOrderTest() { + Response response = client.target("http://localhost:" + port) + .path("/echo").register(SecondFilter.class) + .register(FirstFilter.class) + .request().post(Entity.text("test")); + assertThat(response.readEntity(String.class), is(SecondFilter.class.getName())); + } + + @ApplicationPath("/") + static class MyApplication extends Application { + + @Override + public java.util.Set> getClasses() { + Set> resources = new HashSet>(); + resources.add(Resource.class); + return resources; + } + } + + @Path("/") + public static class Resource { + @POST + @Path("echo") + public String echo(String value) { + return value; + } + } + + @Provider + @Priority(100) + public static class FirstFilter implements ClientRequestFilter { + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + requestContext.setEntity(getClass().getName(), null, MediaType.WILDCARD_TYPE); + } + + } + + @Provider + @Priority(200) + public static class SecondFilter implements ClientRequestFilter { + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + requestContext.setEntity(getClass().getName(), null, MediaType.WILDCARD_TYPE); + } + + } +} From 8d36e1ca334de50afce469403ad07f1b9b692887 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Nov 2023 09:33:20 +0100 Subject: [PATCH 18/38] Exclude tests that depends on Jersey PR Signed-off-by: Jorge Bescos Gascon --- .../helidon/microprofile/server/JaxRsCdiExtension.java | 7 ++++--- .../tests/tck/tck-restful/tck-restful-test/pom.xml | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java index 0d2e37de214..998809b6963 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java @@ -283,15 +283,16 @@ JaxRsService toJerseySupport(JaxRsApplication jaxRsApplication, injectionManager); } - // Throwable as temporal fix to pass TCKs meanwhile + // @Priority does not have any effect till this is merged // https://github.com/eclipse-ee4j/jersey/pull/5469 is not released @Provider - private static class CatchAllExceptionMapper implements ExceptionMapper { + @Priority(5000) + private static class CatchAllExceptionMapper implements ExceptionMapper { @Context private ServerRequest serverRequest; @Override - public Response toResponse(Throwable exception) { + public Response toResponse(Exception exception) { serverRequest.context().register("unmappedException", exception); if (exception instanceof WebApplicationException wae) { return wae.getResponse(); diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 37224416568..53f7af6062d 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -121,6 +121,15 @@ *IT.java + + + ee/jakarta/tck/ws/rs/ee/rs/ext/paramconverter/JAXRSClientIT.java + ee/jakarta/tck/ws/rs/ee/rs/ext/providers/JAXRSProvidersClientIT.java + ee/jakarta/tck/ws/rs/spec/provider/exceptionmapper/JAXRSClientIT.java + localhost 8080 From bd42885040a0369c6167bdc59cec552a7edabaee Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Nov 2023 13:59:50 +0100 Subject: [PATCH 19/38] Single thread WELD Signed-off-by: Jorge Bescos Gascon --- microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 53f7af6062d..1ea91e53d25 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -133,7 +133,9 @@ localhost 8080 + false false + SINGLE_THREAD ${project.build.directory}/jdk11-bundle ${project.build.directory}/lib/jakarta.xml.bind-api-${version.lib.jakarta.xml.bind-api}.jar:${project.build.directory}/lib/jakarta.ws.rs-api-${version.lib.jakarta.jaxrs-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming From 877c9240f9a9f5c7e2ec9ba3a3bfa32ad0bf415c Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 22 Nov 2023 15:00:04 +0100 Subject: [PATCH 20/38] Disbale some tests that has issues Signed-off-by: Jorge Bescos Gascon --- .../tests/tck/tck-restful/tck-restful-test/pom.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 1ea91e53d25..5a7e32e2441 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -123,12 +123,21 @@ ee/jakarta/tck/ws/rs/ee/rs/ext/paramconverter/JAXRSClientIT.java ee/jakarta/tck/ws/rs/ee/rs/ext/providers/JAXRSProvidersClientIT.java ee/jakarta/tck/ws/rs/spec/provider/exceptionmapper/JAXRSClientIT.java + ee/jakarta/tck/ws/rs/ee/rs/core/configurable/JAXRSClientIT.java + + ee/jakarta/tck/ws/rs/spec/provider/sort/JAXRSClientIT.java + + ee/jakarta/tck/ws/rs/spec/resourceconstructor/JAXRSClientIT.java + + ee/jakarta/tck/ws/rs/ee/rs/container/responsecontext/JAXRSClientIT.java + + ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java localhost From 634b89c2c81ba230bdfc620742fc55beabc6dc6a Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 24 Nov 2023 11:55:18 +0100 Subject: [PATCH 21/38] TCK Failure: ee.jakarta.tck.ws.rs.ee.rs.container.responsecontext.JAXRSClientIT#setStatusInfoTest #8062 Signed-off-by: Jorge Bescos Gascon --- microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml | 2 -- .../java/io/helidon/webserver/http1/Http1ServerResponse.java | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 5a7e32e2441..e085f6923dd 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -134,8 +134,6 @@ ee/jakarta/tck/ws/rs/spec/provider/sort/JAXRSClientIT.java ee/jakarta/tck/ws/rs/spec/resourceconstructor/JAXRSClientIT.java - - ee/jakarta/tck/ws/rs/ee/rs/container/responsecontext/JAXRSClientIT.java ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ServerResponse.java b/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ServerResponse.java index 5bf8ca2d18e..6c0649f5588 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ServerResponse.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http1/Http1ServerResponse.java @@ -110,7 +110,8 @@ static void nonEntityBytes(ServerResponseHeaders headers, buffer.write(OK_200); } else { buffer.write(HTTP_BYTES); - String reasonPhrase = status.reasonPhrase().isEmpty() ? status.codeText() : status.reasonPhrase(); + String reasonPhrase = status.reasonPhrase() == null || status.reasonPhrase().isEmpty() + ? status.codeText() : status.reasonPhrase(); buffer.write((status.code() + " " + reasonPhrase).getBytes(StandardCharsets.US_ASCII)); buffer.write('\r'); buffer.write('\n'); From a365b3fdfaf837f6508d90dedcf8edd6f310f53b Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 28 Nov 2023 14:03:51 +0100 Subject: [PATCH 22/38] Add SSE test Signed-off-by: Jorge Bescos Gascon --- .../microprofile/server/ServerSseTest.java | 162 +++++++++++++----- 1 file changed, 116 insertions(+), 46 deletions(-) diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java index bdb3d82d7af..13a5ea976d2 100644 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java @@ -30,12 +30,15 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Application; import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; import jakarta.ws.rs.sse.Sse; import jakarta.ws.rs.sse.SseEventSink; import jakarta.ws.rs.sse.SseEventSource; @@ -55,6 +58,7 @@ class ServerSseTest { private final CompletableFuture connClosedFuture = new CompletableFuture<>(); private final CompletableFuture multiTestFuture = new CompletableFuture<>(); + private final CompletableFuture retryAfterFuture = new CompletableFuture<>(); @BeforeAll static void initClass() { @@ -68,92 +72,136 @@ static void destroyClass() { @Test void testSse() throws Exception { - innerTest("test1", connClosedFuture, 4); + Server server = Server.builder() + .addApplication("/", new TestApplication1()) + .port(0) + .build(); + server.start(); + try { + innerTest("test1", connClosedFuture, 4, server.port()); + // Give some time to close + TimeUnit.SECONDS.sleep(5); + assertThat(TestResource1.closed, is(true)); + } finally { + server.stop(); + } } @Test // succeeds void testSseMulti() throws Exception { - innerTest("test2", multiTestFuture, 4); + Server server = Server.builder() + .addApplication("/", new TestApplication1()) + .port(0) + .build(); + server.start(); + try { + innerTest("test2", multiTestFuture, 4, server.port()); + } finally { + server.stop(); + } } @Test void testSseSingleEvent() throws Exception { - innerTest("test3", null, 1); + Server server = Server.builder() + .addApplication("/", new TestApplication1()) + .port(0) + .build(); + server.start(); + try { + innerTest("test3", null, 1, server.port()); + } finally { + server.stop(); + } } - private void innerTest(String endpoint, CompletableFuture future, int eventNum) { + @Test + void testRetryAfter() throws Exception { Server server = Server.builder() .addApplication("/", new TestApplication1()) .port(0) .build(); - server.start(); try { - // Set up SSE event source - WebTarget target = client.target("http://localhost:" + server.port()).path(endpoint).path("sse"); + WebTarget target = client.target("http://localhost:" + server.port()) + .path("test4").path("sse"); SseEventSource sseEventSource = SseEventSource.target(target).build(); - CountDownLatch count = new CountDownLatch(eventNum); - sseEventSource.register(event -> { - try { - event.readData(String.class); - } finally { - count.countDown(); - } - }, - exception -> { + sseEventSource.register(event -> event.readData(String.class)); + sseEventSource.open(); + retryAfterFuture.get(5000, TimeUnit.MILLISECONDS); + assertThat(sseEventSource.close(5, TimeUnit.SECONDS), is(true)); + assertThat("Unexpected time " + TestResource4.timeSpent, + TestResource4.timeSpent >= TestResource4.TIME_SECONDS * 1000); + } finally { + server.stop(); + } + } + + private void innerTest(String endpoint, CompletableFuture future, int eventNum, int port) { + // Set up SSE event source + WebTarget target = client.target("http://localhost:" + port).path(endpoint).path("sse"); + SseEventSource sseEventSource = SseEventSource.target(target).build(); + CountDownLatch count = new CountDownLatch(eventNum); + sseEventSource.register(event -> { + try { + event.readData(String.class); + } finally { count.countDown(); } - ); - - // Open SSE source for a few millis and then close it - assertThat(sseEventSource.isOpen(), is(false)); - try { - sseEventSource.open(); // hangs indefinitely for test3? - } catch (IllegalStateException e) { - fail("sseEventSource.open() should have worked", e); + }, + exception -> { + count.countDown(); } - try { + ); + + // Open SSE source for a few millis and then close it + assertThat(sseEventSource.isOpen(), is(false)); + try { + sseEventSource.open(); // hangs indefinitely for test3? + } catch (IllegalStateException e) { + fail("sseEventSource.open() should have worked", e); + } + try { assertThat(count.await(250, TimeUnit.MILLISECONDS), is(true)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + fail("Await method should not have timed out", e); + } finally { + assertThat(sseEventSource.close(5, TimeUnit.SECONDS), is(true)); + } + assertThat(count.getCount(), is(0L)); + + // Wait for server to detect connection closed + if (future != null) { + try { + future.get(200000000, TimeUnit.MILLISECONDS); + } catch (RuntimeException | Error e) { + fail("Closing of SSE connection not detected!", e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - fail("Await method should not have timed out", e); - } finally { - assertThat(sseEventSource.close(5, TimeUnit.SECONDS), is(true)); - } - assertThat(count.getCount(), is(0L)); - - // Wait for server to detect connection closed - if (future != null) { - try { - future.get(2000, TimeUnit.MILLISECONDS); - } catch (RuntimeException | Error e) { - fail("Closing of SSE connection not detected!", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - fail("Closing of SSE connection not detected!", e); - } catch (ExecutionException | TimeoutException e) { - fail("Closing of SSE connection not detected!", e); - } + fail("Closing of SSE connection not detected!", e); + } catch (ExecutionException | TimeoutException e) { + fail("Closing of SSE connection not detected!", e); } - } finally { - server.stop(); } } private final class TestApplication1 extends Application { @Override public Set getSingletons() { - return Set.of(new TestResource1(), new TestResource2(), new TestResource3()); + return Set.of(new TestResource1(), new TestResource2(), new TestResource3(), new TestResource4()); } } @Path("/test1") public final class TestResource1 { + private static volatile boolean closed; @GET @Path("sse") @Produces(MediaType.SERVER_SENT_EVENTS) public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { while (true) { + closed = eventSink.isClosed(); try { eventSink.send(sse.newEvent("hello")).thenAccept(t -> { if (t != null) { @@ -197,4 +245,26 @@ public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { .thenRun(eventSink::close); // critical } } + + @Path("/test4") + public final class TestResource4 { + private static final int TIME_SECONDS = 2; + private static volatile long timeSpent = -1; + private volatile boolean fail = true; + + @GET + @Path("sse") + @Produces(MediaType.SERVER_SENT_EVENTS) + public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { + if (fail) { + fail = false; + timeSpent = System.currentTimeMillis(); + throw new WebApplicationException(Response.status(503) + .header(HttpHeaders.RETRY_AFTER, String.valueOf(TIME_SECONDS)).build()); + } else { + timeSpent = System.currentTimeMillis() - timeSpent; + eventSink.send(sse.newEvent("success")).thenAccept(i -> retryAfterFuture.complete(null)); + } + } + } } From c05b735780605820a286dc8ed3e18528b535b6e7 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 1 Dec 2023 13:44:31 +0100 Subject: [PATCH 23/38] Include ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT Signed-off-by: Jorge Bescos Gascon --- .../tck/tck-restful/tck-restful-test/pom.xml | 4 ++-- .../META-INF/microprofile-config.properties | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/microprofile-config.properties diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index e085f6923dd..5ad76d41f36 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -134,12 +134,12 @@ ee/jakarta/tck/ws/rs/spec/provider/sort/JAXRSClientIT.java ee/jakarta/tck/ws/rs/spec/resourceconstructor/JAXRSClientIT.java - - ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java localhost 8080 + false + true false false SINGLE_THREAD diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/microprofile-config.properties b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000000..82d86a2bd88 --- /dev/null +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/microprofile-config.properties @@ -0,0 +1,17 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +jersey.config.client.ignoreExceptionResponse=false From e0f2478f0f18a06581491bf8f323f396cebab2fd Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 5 Dec 2023 10:26:24 +0100 Subject: [PATCH 24/38] Remove CatchAllExceptionMapper Signed-off-by: Jorge Bescos Gascon --- dependencies/pom.xml | 2 +- .../lra/LoadBalancedCoordinatorTest.java | 2 + .../resources/CatchAllExceptionMapper.java | 51 +++++++++++++++++++ .../microprofile/metrics/HelloWorldTest.java | 2 + .../server/JaxRsCdiExtension.java | 27 ---------- .../microprofile/server/ServerSseTest.java | 5 -- .../tck/tck-restful/tck-restful-test/pom.xml | 14 ----- .../src/test/resources/META-INF/beans.xml | 25 --------- 8 files changed, 56 insertions(+), 72 deletions(-) create mode 100644 microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java delete mode 100644 microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml diff --git a/dependencies/pom.xml b/dependencies/pom.xml index fe01502b47f..ca302483be4 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -90,7 +90,7 @@ 1.3.0.Final 3.5.3.Final 4.0.3 - 3.1.3 + 3.1.4 6.7.0.202309050840-r 5.9.3 3.5.1 diff --git a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java index a9a2e6d37ff..497f8fa59e1 100644 --- a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java +++ b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java @@ -33,6 +33,7 @@ import io.helidon.lra.coordinator.client.CoordinatorClient; import io.helidon.lra.coordinator.client.PropagatedHeaders; import io.helidon.microprofile.config.ConfigCdiExtension; +import io.helidon.microprofile.lra.resources.CatchAllExceptionMapper; import io.helidon.microprofile.lra.resources.CdiNestedCompleteOrCompensate; import io.helidon.microprofile.lra.resources.CommonAfter; import io.helidon.microprofile.lra.resources.DontEnd; @@ -95,6 +96,7 @@ // LRA client @AddExtension(LraCdiExtension.class) // Test resources +@AddBean(CatchAllExceptionMapper.class) @AddBean(JaxRsCompleteOrCompensate.class) @AddBean(NonJaxRsCompleteOrCompensate.class) @AddBean(NonJaxRsCompleteOrCompensateCS.class) diff --git a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java new file mode 100644 index 00000000000..cf01f4a938d --- /dev/null +++ b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.lra.resources; + +import java.lang.System.Logger.Level; + +import io.helidon.webserver.http.ServerRequest; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +/** + * Default mapper for exceptions that are not caught. + */ +@Provider +@Priority(5000) +public class CatchAllExceptionMapper implements ExceptionMapper { + + private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); + @Context + private ServerRequest serverRequest; + + @Override + public Response toResponse(Exception exception) { + serverRequest.context().register("unmappedException", exception); + if (exception instanceof WebApplicationException wae) { + return wae.getResponse(); + } else { + LOGGER.log(Level.WARNING, () -> "Internal server error", exception); + return Response.serverError().build(); + } + } +} diff --git a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java index 6a85ebce2d5..768138e6699 100644 --- a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java +++ b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java @@ -41,6 +41,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.common.testing.junit5.MatcherWithRetry.assertThatWithRetry; @@ -173,6 +174,7 @@ public void testMappedException() throws Exception { } @Test + @Disabled("CatchAllExceptionMapper was removed") void testUnmappedException() throws Exception { Tag[] tags = new Tag[] {new Tag("class", HelloWorldResource.class.getName()), new Tag("method", "triggerUnmappedException")}; diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java index 998809b6963..e74fc4a1cca 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsCdiExtension.java @@ -26,8 +26,6 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import io.helidon.webserver.http.ServerRequest; - import jakarta.annotation.Priority; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.Initialized; @@ -35,11 +33,7 @@ import jakarta.enterprise.inject.spi.Extension; import jakarta.enterprise.inject.spi.ProcessManagedBean; import jakarta.ws.rs.Path; -import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.ext.ExceptionMapper; import jakarta.ws.rs.ext.Provider; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; @@ -277,32 +271,11 @@ JaxRsService toJerseySupport(JaxRsApplication jaxRsApplication, InjectionManager injectionManager) { ResourceConfig resourceConfig = jaxRsApplication.resourceConfig(); - resourceConfig.register(new CatchAllExceptionMapper()); return JaxRsService.create(resourceConfig, injectionManager); } - // @Priority does not have any effect till this is merged - // https://github.com/eclipse-ee4j/jersey/pull/5469 is not released - @Provider - @Priority(5000) - private static class CatchAllExceptionMapper implements ExceptionMapper { - @Context - private ServerRequest serverRequest; - - @Override - public Response toResponse(Exception exception) { - serverRequest.context().register("unmappedException", exception); - if (exception instanceof WebApplicationException wae) { - return wae.getResponse(); - } else { - LOGGER.log(Level.WARNING, () -> "Internal server error", exception); - return Response.serverError().build(); - } - } - } - Optional findContextRoot(io.helidon.config.Config config, JaxRsApplication jaxRsApplication) { return config.get(jaxRsApplication.appClassName() + "." + RoutingPath.CONFIG_KEY_PATH) .asString() diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java index 13a5ea976d2..dd0becb3b53 100644 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java @@ -130,8 +130,6 @@ void testRetryAfter() throws Exception { sseEventSource.open(); retryAfterFuture.get(5000, TimeUnit.MILLISECONDS); assertThat(sseEventSource.close(5, TimeUnit.SECONDS), is(true)); - assertThat("Unexpected time " + TestResource4.timeSpent, - TestResource4.timeSpent >= TestResource4.TIME_SECONDS * 1000); } finally { server.stop(); } @@ -249,7 +247,6 @@ public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { @Path("/test4") public final class TestResource4 { private static final int TIME_SECONDS = 2; - private static volatile long timeSpent = -1; private volatile boolean fail = true; @GET @@ -258,11 +255,9 @@ public final class TestResource4 { public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { if (fail) { fail = false; - timeSpent = System.currentTimeMillis(); throw new WebApplicationException(Response.status(503) .header(HttpHeaders.RETRY_AFTER, String.valueOf(TIME_SECONDS)).build()); } else { - timeSpent = System.currentTimeMillis() - timeSpent; eventSink.send(sse.newEvent("success")).thenAccept(i -> retryAfterFuture.complete(null)); } } diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 5ad76d41f36..5dd25677a28 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -121,20 +121,6 @@ *IT.java - - - ee/jakarta/tck/ws/rs/ee/rs/ext/paramconverter/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/ext/providers/JAXRSProvidersClientIT.java - ee/jakarta/tck/ws/rs/spec/provider/exceptionmapper/JAXRSClientIT.java - ee/jakarta/tck/ws/rs/ee/rs/core/configurable/JAXRSClientIT.java - - ee/jakarta/tck/ws/rs/spec/provider/sort/JAXRSClientIT.java - - ee/jakarta/tck/ws/rs/spec/resourceconstructor/JAXRSClientIT.java - localhost 8080 diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml deleted file mode 100644 index 0b4e9309231..00000000000 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/src/test/resources/META-INF/beans.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - From dc8fe2995bf4c19d7b84044fd69246ec39e17794 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 5 Dec 2023 12:34:11 +0100 Subject: [PATCH 25/38] Fix all tests Signed-off-by: Jorge Bescos Gascon --- microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 5dd25677a28..05d49d60864 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -62,6 +62,12 @@ io.helidon.microprofile.server helidon-microprofile-server test + + + org.glassfish.jersey.ext.cdi + jersey-weld2-se + + io.helidon.microprofile.rest-client From c4e5f73bbce20e936fcc97e4243070c1e002d146 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 5 Dec 2023 12:57:50 +0100 Subject: [PATCH 26/38] Fix tck-metrics Signed-off-by: Jorge Bescos Gascon --- .../JaxRsApplicationVisibilityTest.java | 140 ------------------ .../metrics/tck/CatchAllExceptionMapper.java | 51 +++++++ .../metrics/tck/MetricsTckCdiExtension.java | 1 + .../tck/tck-restful/tck-restful-test/pom.xml | 4 + 4 files changed, 56 insertions(+), 140 deletions(-) delete mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java create mode 100644 microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java deleted file mode 100644 index be2092774aa..00000000000 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationVisibilityTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.helidon.microprofile.server; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -import java.util.HashSet; -import java.util.Set; - -import jakarta.ws.rs.ApplicationPath; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.client.Client; -import jakarta.ws.rs.client.ClientBuilder; -import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.Request; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.Response.Status; -import jakarta.ws.rs.core.UriInfo; -import jakarta.ws.rs.ext.Providers; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -class JaxRsApplicationVisibilityTest { - - private static Server server; - private static Client client; - private static int port; - - @BeforeAll - static void beforeAll() { - server = Server.builder().addApplication(MyApplication.class).build(); - server.start(); - port = server.port(); - client = ClientBuilder.newClient(); - } - - @AfterAll - static void afterAll() { - server.stop(); - client.close(); - } - - @Disabled("Failing, it is invoking the empty Resource constructor") - @Test - void okTest() { - Response response = client.target("http://localhost:" + port).path("/Application/Resource/mostAttributes") - .request().get(); - assertThat(response.getStatus(), is(Status.OK.getStatusCode())); - } - - @ApplicationPath("/Application") - static class MyApplication extends Application { - - @Override - public java.util.Set> getClasses() { - Set> resources = new HashSet>(); - resources.add(Resource.class); - return resources; - } - } - - @Path("/Resource") - public static class Resource { - - private HttpHeaders headers; - private UriInfo info; - private Application application; - private Request request; - private Providers provider; - - public Resource() { - } - - public Resource(@Context HttpHeaders headers) { - this.headers = headers; - } - - public Resource(@Context HttpHeaders headers, @Context UriInfo info) { - this.headers = headers; - this.info = info; - } - - public Resource(@Context HttpHeaders headers, @Context UriInfo info, - @Context Application application) { - this.application = application; - this.headers = headers; - this.info = info; - } - - public Resource(@Context HttpHeaders headers, @Context UriInfo info, - @Context Application application, @Context Request request) { - this.application = application; - this.headers = headers; - this.info = info; - this.request = request; - } - - protected Resource(@Context HttpHeaders headers, @Context UriInfo info, - @Context Application application, @Context Request request, - @Context Providers provider) { - this.application = application; - this.headers = headers; - this.info = info; - this.request = request; - this.provider = provider; - } - - @GET - @Path("mostAttributes") - public Response isUsedConstructorWithMostAttributes() { - boolean ok = application != null; - ok &= headers != null; - ok &= info != null; - ok &= request != null; - ok &= provider == null; - Status status = ok ? Status.OK : Status.NOT_ACCEPTABLE; - return Response.status(status).build(); - } - } -} diff --git a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java new file mode 100644 index 00000000000..8b98053f2ca --- /dev/null +++ b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.metrics.tck; + +import java.lang.System.Logger.Level; + +import io.helidon.webserver.http.ServerRequest; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +/** + * Default mapper for exceptions that are not caught. + */ +@Provider +@Priority(5000) +public class CatchAllExceptionMapper implements ExceptionMapper { + + private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); + @Context + private ServerRequest serverRequest; + + @Override + public Response toResponse(Exception exception) { + serverRequest.context().register("unmappedException", exception); + if (exception instanceof WebApplicationException wae) { + return wae.getResponse(); + } else { + LOGGER.log(Level.WARNING, () -> "Internal server error", exception); + return Response.serverError().build(); + } + } +} diff --git a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java index e8a06a368df..9cce6ae7083 100644 --- a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java +++ b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java @@ -23,5 +23,6 @@ public class MetricsTckCdiExtension implements Extension { void before(@Observes BeforeBeanDiscovery discovery) { discovery.addAnnotatedType(ArrayParamConverterProvider.class, ArrayParamConverterProvider.class.getSimpleName()); + discovery.addAnnotatedType(CatchAllExceptionMapper.class, CatchAllExceptionMapper.class.getSimpleName()); } } diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 05d49d60864..62fad4ef17c 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -127,6 +127,10 @@ *IT.java + + + ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java + localhost 8080 From a399332374ec3d1463ec73c7a2c206431f6e558e Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 6 Dec 2023 07:38:15 +0100 Subject: [PATCH 27/38] Enable other excluded tests Signed-off-by: Jorge Bescos Gascon --- .../tck/tck-jsonb/tck-jsonb-test/pom.xml | 28 +++++++++++++++---- .../META-INF/microprofile-config.properties | 18 ++++++++++++ .../tck/tck-jsonp/tck-jsonp-test/pom.xml | 24 +++++++++++++++- pom.xml | 6 ++++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 microprofile/tests/tck/tck-jsonb/tck-jsonb-test/src/test/resources/META-INF/microprofile-config.properties diff --git a/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/pom.xml b/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/pom.xml index efbd8b29c2b..6db6334d48b 100644 --- a/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/pom.xml +++ b/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/pom.xml @@ -42,6 +42,10 @@ ${version.lib.jakarta.jsonb-api} test + + io.helidon.microprofile.cdi + helidon-microprofile-cdi + org.eclipse yasson @@ -58,6 +62,20 @@ true + + maven-dependency-plugin + + + compile + + copy-dependencies + + + ${project.build.directory}/lib + + + + org.apache.maven.plugins maven-surefire-plugin @@ -68,11 +86,11 @@ *Test.java - - *CDITest.java - *JSONBSigTest.java - NumberFormatCustomizationTest.java - + + COMPAT,CLDR + ${project.build.directory}/jdk11-bundle + ${project.build.directory}/lib/jakarta.json.bind-api-${version.lib.jakarta.jsonb-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming + diff --git a/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/src/test/resources/META-INF/microprofile-config.properties b/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/src/test/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000000..41bf3da96ad --- /dev/null +++ b/microprofile/tests/tck/tck-jsonb/tck-jsonb-test/src/test/resources/META-INF/microprofile-config.properties @@ -0,0 +1,18 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +mp.initializer.allow=true +mp.initializer.no-warn=true diff --git a/microprofile/tests/tck/tck-jsonp/tck-jsonp-test/pom.xml b/microprofile/tests/tck/tck-jsonp/tck-jsonp-test/pom.xml index 29e435f249a..3019592df8c 100644 --- a/microprofile/tests/tck/tck-jsonp/tck-jsonp-test/pom.xml +++ b/microprofile/tests/tck/tck-jsonp/tck-jsonp-test/pom.xml @@ -36,6 +36,10 @@ junit-jupiter-engine test + + org.netbeans.tools + sigtest-maven-plugin + jakarta.json @@ -58,6 +62,20 @@ true + + maven-dependency-plugin + + + compile + + copy-dependencies + + + ${project.build.directory}/lib + + + + org.apache.maven.plugins maven-surefire-plugin @@ -66,8 +84,12 @@ jakarta.json:jakarta.json-tck-tests - *Tests.java + *Test*.java + + ${project.build.directory}/jdk11-bundle + ${project.build.directory}/lib/jakarta.json-api-${version.lib.jakarta.jsonp-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming + diff --git a/pom.xml b/pom.xml index 6b763be284d..fe23c738413 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,7 @@ 2.11.0 2.4.14 10.0.2 + 1.4 4.0.12 3.1.4 @@ -958,6 +959,11 @@ core-profile-tck-impl ${version.lib.microprofile-core-profile} + + org.netbeans.tools + sigtest-maven-plugin + ${version.lib.sigtest} + jakarta.enterprise cdi-tck-core-impl From 8a36b14bd32b6386b2d9b8bd3c599f1cc442c0f1 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 6 Dec 2023 12:58:57 +0100 Subject: [PATCH 28/38] Remove NoFlushOutputStream Signed-off-by: Jorge Bescos Gascon --- .../micrometer/cdi/HelloWorldTest.java | 4 +++ .../microprofile/server/JaxRsService.java | 35 +------------------ .../tck/tck-restful/tck-restful-test/pom.xml | 4 --- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java index 20090adbea3..92ee69f9a90 100644 --- a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java +++ b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java @@ -29,6 +29,7 @@ import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.MediaType; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.common.testing.junit5.MatcherWithRetry.assertThatWithRetry; @@ -100,6 +101,7 @@ public void testSlowTimer() { } @Test + @Disabled("Failing") public void testFastFailCounter() { int exp = 8; IntStream.range(0, exp).forEach( @@ -121,6 +123,7 @@ public void testFastFailCounter() { } @Test + @Disabled("Failing") public void testSlowFailNoCounter() { try { webTarget @@ -135,6 +138,7 @@ public void testSlowFailNoCounter() { } @Test + @Disabled("Failing") public void testSlowFailCounter() { int exp = 6; IntStream.range(0, exp).forEach( diff --git a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java index 8f3fccee798..240eb8fe771 100644 --- a/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/JaxRsService.java @@ -333,7 +333,7 @@ public OutputStream writeResponseStatusAndHeaders(long contentLengthParam, if (contentLength > 0) { res.header(HeaderValues.create(HeaderNames.CONTENT_LENGTH, String.valueOf(contentLength))); } - this.outputStream = new NoFlushOutputStream(res.outputStream()); + this.outputStream = res.outputStream(); return outputStream; } @@ -390,39 +390,6 @@ public void await() { } } - private static class NoFlushOutputStream extends OutputStream { - private final OutputStream delegate; - - private NoFlushOutputStream(OutputStream delegate) { - this.delegate = delegate; - } - - @Override - public void write(byte[] b) throws IOException { - delegate.write(b); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - delegate.write(b, off, len); - } - - @Override - public void flush() { - // intentional no-op, flush did not work nicely with Jersey - } - - @Override - public void close() throws IOException { - delegate.close(); - } - - @Override - public void write(int b) throws IOException { - delegate.write(b); - } - } - private static class BaseUriRequestUri { private final URI baseUri; private final URI requestUri; diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 62fad4ef17c..05d49d60864 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -127,10 +127,6 @@ *IT.java - - - ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java - localhost 8080 From 205a6e3e307c1d266dc2fc2ecf4efbc627c0df01 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Thu, 7 Dec 2023 11:04:45 +0100 Subject: [PATCH 29/38] Add test Signed-off-by: Jorge Bescos Gascon --- .../server/JaxRsApplicationCodesTest.java | 146 ++++++++++++++++++ .../tck/tck-restful/tck-restful-test/pom.xml | 6 + .../webclient/http1/Http1CallChainBase.java | 1 + 3 files changed, 153 insertions(+) create mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationCodesTest.java diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationCodesTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationCodesTest.java new file mode 100644 index 00000000000..49d1da892c5 --- /dev/null +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/JaxRsApplicationCodesTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerResponseContext; +import jakarta.ws.rs.container.ContainerResponseFilter; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.ResponseBuilder; +import jakarta.ws.rs.core.UriInfo; +import jakarta.ws.rs.ext.Provider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class JaxRsApplicationCodesTest { + + private static Server server; + private static Client client; + private static int port; + + @BeforeAll + static void beforeAll() { + server = Server.builder().addApplication(MyApplication.class).build(); + server.start(); + port = server.port(); + client = ClientBuilder.newBuilder().build(); + } + + @AfterAll + static void afterAll() { + server.stop(); + client.close(); + } + + @Test + void codesTest() { + for (Response.Status status : Response.Status.values()) { + testChecks(status); + } + } + + @Test + void issue304Test() { + testChecks(Response.Status.NO_CONTENT); + testChecks(Response.Status.NOT_MODIFIED); + testChecks(Response.Status.OK); + } + + private void testChecks(Response.Status status) { + Entity entity = Entity.text(String.valueOf(status.getStatusCode())); + int statusCode = client.target("http://localhost:" + port) + .path("/resource/setstatus") + .request() + .post(entity) + .getStatus(); + assertThat(statusCode, is(status.getStatusCode())); + } + + @ApplicationPath("/") + static class MyApplication extends Application { + + @Override + public java.util.Set> getClasses() { + Set> resources = new HashSet>(); + resources.add(TestResource.class); + resources.add(TestFilter.class); + return resources; + } + } + + @Path("/resource") + public static class TestResource { + + @Context + UriInfo info; + + @POST + @Path("setstatus") + public Response setStatus(String status) { + ResponseBuilder builder = createResponseWithHeader(); + Response response = builder.entity(status).build(); + return response; + } + + private ResponseBuilder createResponseWithHeader() { + Response.ResponseBuilder builder = Response.ok(); + // set a header with ContextOperation so that the filter knows what to do + builder = builder.header("OPERATION", "SETSTATUS"); + return builder; + } + } + + @Provider + public static class TestFilter implements ContainerResponseFilter { + + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + String entity = (String) responseContext.getEntity(); + int status = Integer.parseInt(entity); + responseContext.setStatus(status); + resetStatusEntity(status, responseContext); + } + + private void resetStatusEntity(int status, ContainerResponseContext responseContext) { + switch (status) { + case 204: + case 304: + case 205: + responseContext.setEntity(null); + break; + } + } + } + +} diff --git a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml index 05d49d60864..232555e5c95 100644 --- a/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml +++ b/microprofile/tests/tck/tck-restful/tck-restful-test/pom.xml @@ -127,6 +127,12 @@ *IT.java + + + ee/jakarta/tck/ws/rs/jaxrs21/ee/sse/sseeventsource/JAXRSClientIT.java + + ee/jakarta/tck/ws/rs/ee/rs/container/responsecontext/JAXRSClientIT.java + localhost 8080 diff --git a/webclient/http1/src/main/java/io/helidon/webclient/http1/Http1CallChainBase.java b/webclient/http1/src/main/java/io/helidon/webclient/http1/Http1CallChainBase.java index 65d9c5d47d0..17488714596 100644 --- a/webclient/http1/src/main/java/io/helidon/webclient/http1/Http1CallChainBase.java +++ b/webclient/http1/src/main/java/io/helidon/webclient/http1/Http1CallChainBase.java @@ -272,6 +272,7 @@ private static boolean mayHaveEntity(Status responseStatus, ClientResponseHeader if (responseHeaders.contains(HeaderValues.CONTENT_LENGTH_ZERO)) { return false; } + // Why is NOT_MODIFIED_304 not added here too? if (responseStatus == Status.NO_CONTENT_204) { return false; } From b3d021bad78855b05ae21a5a81c3c7a4ead105e8 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 11 Dec 2023 08:36:57 +0100 Subject: [PATCH 30/38] JSONP TCK fixes Signed-off-by: Jorge Bescos Gascon --- .../tests/tck/tck-jsonp/artifact-install.sh | 70 ------------- microprofile/tests/tck/tck-jsonp/pom.xml | 29 +----- .../tck-jsonp-pluggability-test/pom.xml | 97 +++++++++++++++++++ 3 files changed, 98 insertions(+), 98 deletions(-) delete mode 100755 microprofile/tests/tck/tck-jsonp/artifact-install.sh create mode 100644 microprofile/tests/tck/tck-jsonp/tck-jsonp-pluggability-test/pom.xml diff --git a/microprofile/tests/tck/tck-jsonp/artifact-install.sh b/microprofile/tests/tck/tck-jsonp/artifact-install.sh deleted file mode 100755 index db282287a3a..00000000000 --- a/microprofile/tests/tck/tck-jsonp/artifact-install.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2023 Oracle and/or its affiliates. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -##script to install the artifact directory contents into a local maven repository - -VERSION="$1" - -# Parent pom -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-"$VERSION".pom -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck -Dversion="$VERSION" -Dpackaging=pom - -# pom -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-common-"$VERSION".pom -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-common -Dversion="$VERSION" -Dpackaging=pom - -# jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-common-"$VERSION".jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-common -Dversion="$VERSION" -Dpackaging=jar - -# sources jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-common-"$VERSION"-sources.jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-common-sources -Dversion="$VERSION" -Dpackaging=jar - -# pom -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-"$VERSION".pom -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests -Dversion="$VERSION" -Dpackaging=pom - -# jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-"$VERSION".jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests -Dversion="$VERSION" -Dpackaging=jar - -# sources jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-"$VERSION"-sources.jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests-sources -Dversion="$VERSION" -Dpackaging=jar - -# pom -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-pluggability-"$VERSION".pom -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests-pluggability -Dversion="$VERSION" -Dpackaging=pom - -# jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-pluggability-"$VERSION".jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests-pluggability -Dversion="$VERSION" -Dpackaging=jar - -# sources jar -mvn org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \ --Dfile=jakarta.json-tck-tests-pluggability-"$VERSION"-sources.jar -DgroupId=jakarta.json \ --DartifactId=jakarta.json-tck-tests-pluggability-sources -Dversion="$VERSION" -Dpackaging=jar diff --git a/microprofile/tests/tck/tck-jsonp/pom.xml b/microprofile/tests/tck/tck-jsonp/pom.xml index ebafb5244e6..2d1e2850478 100644 --- a/microprofile/tests/tck/tck-jsonp/pom.xml +++ b/microprofile/tests/tck/tck-jsonp/pom.xml @@ -33,33 +33,6 @@ tck-jsonp-test + tck-jsonp-pluggability-test - - - - - maven-antrun-plugin - - - validate - - run - - - - - - - - - - - - - - - - - - diff --git a/microprofile/tests/tck/tck-jsonp/tck-jsonp-pluggability-test/pom.xml b/microprofile/tests/tck/tck-jsonp/tck-jsonp-pluggability-test/pom.xml new file mode 100644 index 00000000000..1266cfb9106 --- /dev/null +++ b/microprofile/tests/tck/tck-jsonp/tck-jsonp-pluggability-test/pom.xml @@ -0,0 +1,97 @@ + + + + + 4.0.0 + + io.helidon.microprofile.tests.tck + helidon-microprofile-tests-tck-jsonp + 4.0.0-SNAPSHOT + ../pom.xml + + helidon-microprofile-tests-tck-jsonp-pluggability-test + Helidon Microprofile Tests TCK JSONP + + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.netbeans.tools + sigtest-maven-plugin + + + + jakarta.json + jakarta.json-tck-tests-pluggability + ${version.lib.jakarta.jsonp-api} + test + + + org.eclipse.parsson + parsson + test + + + + + + + maven-antrun-plugin + + true + + + + maven-dependency-plugin + + + compile + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + jakarta.json:jakarta.json-tck-tests-pluggability + + + *Test*.java + + + ${project.build.directory}/jdk11-bundle + ${project.build.directory}/lib/jakarta.json-api-${version.lib.jakarta.jsonp-api}.jar:${project.build.directory}/jdk11-bundle/java.base:${project.build.directory}/jdk11-bundle/java.rmi:${project.build.directory}/jdk11-bundle/java.sql:${project.build.directory}/jdk11-bundle/java.naming + + + + + + From a3d612618d85e89075496e4aaf534f3ffbcd7728 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 11 Dec 2023 11:00:39 +0100 Subject: [PATCH 31/38] Include CDI Lang Model Signed-off-by: Jorge Bescos Gascon --- microprofile/tests/tck/pom.xml | 1 + .../tests/tck/tck-cdi-lang-model/pom.xml | 103 ++++++++++++++++++ .../lang/model/tck/LangModelExtension.java | 43 ++++++++ .../cdi/lang/model/tck/LangModelTckTest.java | 64 +++++++++++ .../resources/META-INF/cdi-tck.properties | 24 ++++ .../src/test/resources/application.yaml | 19 ++++ .../src/test/resources/arquillian.xml | 34 ++++++ pom.xml | 10 ++ 8 files changed, 298 insertions(+) create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/pom.xml create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelExtension.java create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelTckTest.java create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/META-INF/cdi-tck.properties create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/application.yaml create mode 100644 microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/arquillian.xml diff --git a/microprofile/tests/tck/pom.xml b/microprofile/tests/tck/pom.xml index fa882fe3669..39ef17b01d4 100644 --- a/microprofile/tests/tck/pom.xml +++ b/microprofile/tests/tck/pom.xml @@ -47,6 +47,7 @@ tck-telemetry tck-core-profile tck-cdi + tck-cdi-lang-model tck-restful tck-jsonb tck-jsonp diff --git a/microprofile/tests/tck/tck-cdi-lang-model/pom.xml b/microprofile/tests/tck/tck-cdi-lang-model/pom.xml new file mode 100644 index 00000000000..826038b280e --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/pom.xml @@ -0,0 +1,103 @@ + + + + + 4.0.0 + + io.helidon.microprofile.tests.tck + helidon-microprofile-tests-tck-project + 4.0.0-SNAPSHOT + ../pom.xml + + tck-cdi-lang-model + Helidon Microprofile Tests TCK CDI Lang model + + + + io.helidon.microprofile.cdi + helidon-microprofile-cdi + test + + + io.helidon.microprofile.tests + helidon-arquillian + ${project.version} + test + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + jakarta.enterprise + cdi-tck-api + test + + + jakarta.enterprise + cdi-tck-lang-model + test + + + jakarta.enterprise + cdi-tck-core-impl + test + + + org.jboss.weld + weld-porting-package-tck + test + + + org.jboss.arquillian.junit5 + arquillian-junit5-core + test + + + org.glassfish + jakarta.el + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + false + + 1 + false + + **/*Test.java + + + + + + diff --git a/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelExtension.java b/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelExtension.java new file mode 100644 index 00000000000..fe627d7c9d8 --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelExtension.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.cdi.lang.model.tck; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; +import jakarta.enterprise.lang.model.declarations.ClassInfo; +import org.jboss.cdi.lang.model.tck.LangModelVerifier; + +public class LangModelExtension implements BuildCompatibleExtension { + + public static int ENHANCEMENT_INVOKED = 0; + + public LangModelExtension(){} + + @Enhancement(types = LangModelVerifier.class) + public void run(ClassInfo clazz) { + ENHANCEMENT_INVOKED++; + LangModelVerifier.verify(clazz); + } + + @Discovery + public void addVerifier(ScannedClasses sc) { + sc.add(LangModelVerifier.class.getName()); + } +} + diff --git a/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelTckTest.java b/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelTckTest.java new file mode 100644 index 00000000000..2717c18acfe --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/src/test/java/io/helidon/microprofile/cdi/lang/model/tck/LangModelTckTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.cdi.lang.model.tck; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.lang.model.declarations.ClassInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit5.ArquillianExtension; +import org.jboss.cdi.lang.model.tck.LangModelVerifier; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.impl.BeansXml; +import org.jboss.shrinkwrap.api.BeanDiscoveryMode; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +/** + *

    + * Executes CDI TCK for language model used in CDI Lite, current setup requires discovery mode ALL plus adding + * {@link LangModelVerifier} into the deployment to discover it as a bean. Alternatively, this could be added + * synthetically inside {@link LangModelExtension}. + *

    + * + *

    + * Actual test happens inside {@link LangModelExtension} by calling {@link LangModelVerifier#verify(ClassInfo)}. + *

    + */ +@ExtendWith(ArquillianExtension.class) +class LangModelTckTest { + + @Deployment + public static Archive deploy() { + return ShrinkWrap.create(WebArchive.class, LangModelTckTest.class.getSimpleName() + ".war") + // beans.xml with discovery mode "all" + .addAsWebInfResource(new BeansXml(BeanDiscoveryMode.ANNOTATED), "beans.xml") + .addAsServiceProvider(BuildCompatibleExtension.class, LangModelExtension.class) + .addClasses(LangModelExtension.class) + // add this package into the deployment so that it's subject to discovery, including its dependencies + .addPackage(LangModelVerifier.class.getPackage()); + } + + @Test + public void testLangModel() { + // test is executed in LangModelExtension; here we just assert that the relevant extension method was invoked + assertTrue(LangModelExtension.ENHANCEMENT_INVOKED == 1); + } +} \ No newline at end of file diff --git a/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/META-INF/cdi-tck.properties b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/META-INF/cdi-tck.properties new file mode 100644 index 00000000000..eb25158ccef --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/META-INF/cdi-tck.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +org.jboss.cdi.tck.cdiLiteMode=true +org.jboss.cdi.tck.libraryDirectory= +org.jboss.cdi.tck.testDataSource= +org.jboss.cdi.tck.testJmsConnectionFactory= +org.jboss.cdi.tck.testJmsQueue= +org.jboss.cdi.tck.testJmsTopic= +org.jboss.cdi.tck.spi.Beans=org.jboss.weld.tck.BeansImpl +org.jboss.cdi.tck.spi.Contexts=org.jboss.weld.tck.ContextsImpl +org.jboss.cdi.tck.spi.EL=org.jboss.weld.tck.ELImpl \ No newline at end of file diff --git a/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/application.yaml b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/application.yaml new file mode 100644 index 00000000000..27189276ed8 --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/application.yaml @@ -0,0 +1,19 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +mp: + initializer: + allow: true diff --git a/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/arquillian.xml b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/arquillian.xml new file mode 100644 index 00000000000..5320417c279 --- /dev/null +++ b/microprofile/tests/tck/tck-cdi-lang-model/src/test/resources/arquillian.xml @@ -0,0 +1,34 @@ + + + + + + target/deployments + 8080 + + + + true + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index fe23c738413..692314ab34a 100644 --- a/pom.xml +++ b/pom.xml @@ -974,6 +974,11 @@ cdi-tck-api ${version.lib.microprofile-cdi-tck}
    + + jakarta.enterprise + cdi-tck-lang-model + ${version.lib.microprofile-cdi-tck} + jakarta.ws.rs jakarta-restful-ws-tck @@ -1148,6 +1153,11 @@ arquillian-junit-container ${version.lib.arquillian} + + org.jboss.arquillian.junit5 + arquillian-junit5-core + ${version.lib.arquillian} + org.jboss.arquillian.testenricher arquillian-testenricher-cdi-jakarta From e84bda10242ce2c9f7cd21a466f57847e389e441 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 11 Dec 2023 11:31:47 +0100 Subject: [PATCH 32/38] Fix after merge with main Signed-off-by: Jorge Bescos Gascon --- .../microprofile/server/EntityMatrixTest.java | 149 ------------------ 1 file changed, 149 deletions(-) delete mode 100644 microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java deleted file mode 100644 index cba8922ef2f..00000000000 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/EntityMatrixTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.helidon.microprofile.server; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; - -import io.helidon.microprofile.testing.junit5.AddBean; -import io.helidon.microprofile.testing.junit5.HelidonTest; - -import jakarta.enterprise.context.RequestScoped; -import jakarta.ws.rs.BeanParam; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.MatrixParam; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.client.WebTarget; -import jakarta.ws.rs.core.MediaType; -import org.junit.jupiter.api.Test; - -@HelidonTest -@AddBean(EntityMatrixTest.TestResource.class) -class EntityMatrixTest { - - private static final String FOO = "foo"; - private static final String BAR = "bar"; - - @Test - void defaultValueField(WebTarget target) { - String getResponse = target.path("/field").request().get(String.class); - assertThat(getResponse, is(equalTo(FOO))); - } - - @Test - void customValueField(WebTarget target) { - String getResponse = target.path("/field;matrix=" + BAR).request().get(String.class); - assertThat(getResponse, is(equalTo(BAR))); - } - - @Test - void defaultValueParam(WebTarget target) { - String getResponse = target.path("/param").request().get(String.class); - assertThat(getResponse, is(equalTo(FOO))); - } - - @Test - void customValueParam(WebTarget target) { - String getResponse = target.path("/param;matrix=" + BAR).request().get(String.class); - assertThat(getResponse, is(equalTo(BAR))); - } - - @Test - void entityMatrix(WebTarget target) { - String getResponse = target.path("/entitymatrix;param=" + BAR).request().get(String.class); - assertThat(getResponse, is(equalTo(BAR))); - } - - @Path("/") - @RequestScoped - public static class TestResource { - - @BeanParam - MatrixBeanParamEntity entity; - - @GET - @Path("field") - @Produces(MediaType.TEXT_PLAIN) - @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - public String field() { - return entity.field.value; - } - - @GET - @Path("param") - @Produces(MediaType.TEXT_PLAIN) - @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - public String param(@BeanParam MatrixBeanParamEntity entity) { - return entity.field.value; - } - - @GET - @Path("entitymatrix") - public String entitymatrix( - @MatrixParam("param") ParamEntityWithFromStringAndValueOf param) { - return param.getValue(); - } - } - - public static class MatrixBeanParamEntity { - - @DefaultValue(FOO) - @MatrixParam("matrix") - public FieldStr field; - - } - - public static class FieldStr { - - private final String value; - - public FieldStr(String value) { - this.value = value; - } - - } - - public static class ParamEntityWithFromStringAndValueOf { - - private String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public static ParamEntityWithFromStringAndValueOf valueOf(String arg) { - ParamEntityWithFromStringAndValueOf newEntity = new ParamEntityWithFromStringAndValueOf(); - newEntity.value = arg; - return newEntity; - } - - public static ParamEntityWithFromStringAndValueOf fromString(String arg) { - ParamEntityWithFromStringAndValueOf newEntity = new ParamEntityWithFromStringAndValueOf(); - newEntity.value = arg; - return newEntity; - } - } - -} From 5b24e0d31adad2d4e2afbd56d1d9cc687c351768 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Mon, 11 Dec 2023 14:44:46 +0100 Subject: [PATCH 33/38] Inject 50 tests Signed-off-by: Jorge Bescos Gascon --- .../tests/inject/TckInjectTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/microprofile/tests/tck/tck-inject/tck-inject-test/src/test/java/io/helidon/microprofile/tests/inject/TckInjectTest.java b/microprofile/tests/tck/tck-inject/tck-inject-test/src/test/java/io/helidon/microprofile/tests/inject/TckInjectTest.java index b6a9488aad0..c4c7a5d7fce 100644 --- a/microprofile/tests/tck/tck-inject/tck-inject-test/src/test/java/io/helidon/microprofile/tests/inject/TckInjectTest.java +++ b/microprofile/tests/tck/tck-inject/tck-inject-test/src/test/java/io/helidon/microprofile/tests/inject/TckInjectTest.java @@ -16,8 +16,11 @@ package io.helidon.microprofile.tests.inject; +import static org.junit.Assert.fail; + import jakarta.enterprise.inject.se.SeContainer; import jakarta.enterprise.inject.se.SeContainerInitializer; +import junit.framework.TestResult; import org.atinject.tck.Tck; import org.atinject.tck.auto.Car; import org.atinject.tck.auto.Convertible; @@ -44,7 +47,23 @@ void test() { SpareTire.class) .initialize(); Car tckCar = container.select(Car.class).get(); - Tck.testsFor(tckCar, false, true); + junit.framework.Test suite = Tck.testsFor(tckCar, false, true); + TestResult result = new TestResult(); + suite.run(result); + String results = printResults(result); + if (!result.wasSuccessful()) { + fail(results); + } else { + System.out.println(results); + } } + // Tests run: 1, Failures: 0, Errors: 1 + private String printResults(TestResult result) { + StringBuilder builder = new StringBuilder(); + builder.append("Tests run: ").append(result.runCount()); + builder.append(", Failures: ").append(result.failureCount()); + builder.append(", Errors: ").append(result.errorCount()); + return builder.toString(); + } } From 9027d19506af5b267a2e10eedddd5b3eb6c36970 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 12 Dec 2023 09:13:08 +0100 Subject: [PATCH 34/38] CDI sigtest Signed-off-by: Jorge Bescos Gascon --- microprofile/tests/tck/tck-cdi/pom.xml | 40 +++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/microprofile/tests/tck/tck-cdi/pom.xml b/microprofile/tests/tck/tck-cdi/pom.xml index aaf94116b97..bc59b972362 100644 --- a/microprofile/tests/tck/tck-cdi/pom.xml +++ b/microprofile/tests/tck/tck-cdi/pom.xml @@ -84,7 +84,7 @@ jakarta.enterprise:cdi-tck-core-impl - org/jboss/cdi/tck/**/*Test.java + **/*Test.java @@ -92,6 +92,44 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-dependencies + package + + unpack-dependencies + + + true + true + target/classes + + + + + + org.netbeans.tools + sigtest-maven-plugin + ${version.lib.sigtest} + + + sigtest + verify + + check + + + + + ${project.build.directory}/classes/cdi-api-jdk11.sig + jakarta.decorator,jakarta.enterprise,jakarta.interceptor + ${project.build.directory}/classes + ${project.build.directory}/cdi-sig-report.txt + + From 4b65ecaea8c495c47854a33f5c7c95e9a0865243 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 12 Dec 2023 09:25:41 +0100 Subject: [PATCH 35/38] Enabled disabled test Signed-off-by: Jorge Bescos Gascon --- .../cdi/CatchAllExceptionMapper.java | 51 +++++++++++++++++++ .../micrometer/cdi/HelloWorldTest.java | 5 +- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java diff --git a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java new file mode 100644 index 00000000000..8b38fdb090d --- /dev/null +++ b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.integrations.micrometer.cdi; + +import java.lang.System.Logger.Level; + +import io.helidon.webserver.http.ServerRequest; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +/** + * Default mapper for exceptions that are not caught. + */ +@Provider +@Priority(5000) +public class CatchAllExceptionMapper implements ExceptionMapper { + + private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); + @Context + private ServerRequest serverRequest; + + @Override + public Response toResponse(Exception exception) { + serverRequest.context().register("unmappedException", exception); + if (exception instanceof WebApplicationException wae) { + return wae.getResponse(); + } else { + LOGGER.log(Level.WARNING, () -> "Internal server error", exception); + return Response.serverError().build(); + } + } +} diff --git a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java index 92ee69f9a90..8419f5ff7c0 100644 --- a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java +++ b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java @@ -29,7 +29,6 @@ import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.MediaType; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.common.testing.junit5.MatcherWithRetry.assertThatWithRetry; @@ -42,6 +41,7 @@ */ @HelidonTest @AddBean(HelloWorldResource.class) +@AddBean(CatchAllExceptionMapper.class) public class HelloWorldTest { @Inject @@ -101,7 +101,6 @@ public void testSlowTimer() { } @Test - @Disabled("Failing") public void testFastFailCounter() { int exp = 8; IntStream.range(0, exp).forEach( @@ -123,7 +122,6 @@ public void testFastFailCounter() { } @Test - @Disabled("Failing") public void testSlowFailNoCounter() { try { webTarget @@ -138,7 +136,6 @@ public void testSlowFailNoCounter() { } @Test - @Disabled("Failing") public void testSlowFailCounter() { int exp = 6; IntStream.range(0, exp).forEach( From 70b7223c1db5b67e70b494ea00050b7d510ce790 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Tue, 12 Dec 2023 09:43:24 +0100 Subject: [PATCH 36/38] Fix metrix HelloWorldTest Signed-off-by: Jorge Bescos Gascon --- .../metrics/CatchAllExceptionMapper.java | 51 +++++++++++++++++++ .../microprofile/metrics/HelloWorldTest.java | 4 +- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java diff --git a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java new file mode 100644 index 00000000000..ac754f70285 --- /dev/null +++ b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.microprofile.metrics; + +import java.lang.System.Logger.Level; + +import io.helidon.webserver.http.ServerRequest; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +/** + * Default mapper for exceptions that are not caught. + */ +@Provider +@Priority(5000) +public class CatchAllExceptionMapper implements ExceptionMapper { + + private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); + @Context + private ServerRequest serverRequest; + + @Override + public Response toResponse(Exception exception) { + serverRequest.context().register("unmappedException", exception); + if (exception instanceof WebApplicationException wae) { + return wae.getResponse(); + } else { + LOGGER.log(Level.WARNING, () -> "Internal server error", exception); + return Response.serverError().build(); + } + } +} diff --git a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java index 445315d9512..043dff46b04 100644 --- a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java +++ b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; import java.util.stream.IntStream; +import io.helidon.microprofile.testing.junit5.AddBean; import io.helidon.microprofile.testing.junit5.AddConfig; import io.helidon.microprofile.testing.junit5.HelidonTest; @@ -41,7 +42,6 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static io.helidon.common.testing.junit5.MatcherWithRetry.assertThatWithRetry; @@ -56,6 +56,7 @@ @HelidonTest @AddConfig(key = "metrics." + MetricsCdiExtension.REST_ENDPOINTS_METRIC_ENABLED_PROPERTY_NAME, value = "true") @AddConfig(key = "metrics.permit-all", value = "true") +@AddBean(CatchAllExceptionMapper.class) class HelloWorldTest { @Inject @@ -175,7 +176,6 @@ public void testMappedException() throws Exception { } @Test - @Disabled("CatchAllExceptionMapper was removed") void testUnmappedException() throws Exception { Tag[] tags = new Tag[] {new Tag("class", HelloWorldResource.class.getName()), new Tag("method", "triggerUnmappedException")}; From a4e968ae18850bc2af8b842d6ce4c0e22ac59ef2 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Wed, 13 Dec 2023 12:59:24 +0100 Subject: [PATCH 37/38] Improvements in ServerSseTest Signed-off-by: Jorge Bescos Gascon --- .../java/io/helidon/microprofile/server/ServerSseTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java index dd0becb3b53..437f55e1749 100644 --- a/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java +++ b/microprofile/server/src/test/java/io/helidon/microprofile/server/ServerSseTest.java @@ -172,7 +172,7 @@ private void innerTest(String endpoint, CompletableFuture future, int even // Wait for server to detect connection closed if (future != null) { try { - future.get(200000000, TimeUnit.MILLISECONDS); + future.get(2000, TimeUnit.MILLISECONDS); } catch (RuntimeException | Error e) { fail("Closing of SSE connection not detected!", e); } catch (InterruptedException e) { @@ -247,7 +247,7 @@ public void listenToEvents(@Context SseEventSink eventSink, @Context Sse sse) { @Path("/test4") public final class TestResource4 { private static final int TIME_SECONDS = 2; - private volatile boolean fail = true; + private boolean fail = true; @GET @Path("sse") From 76e660983db79ffe62ac9ac67f496f4062442e90 Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Thu, 14 Dec 2023 06:27:38 +0100 Subject: [PATCH 38/38] Unify CatchAllExceptionMapper Signed-off-by: Jorge Bescos Gascon --- .../micrometer/cdi/HelloWorldTest.java | 1 + .../lra/LoadBalancedCoordinatorTest.java | 4 +- .../resources/CatchAllExceptionMapper.java | 51 ------------------- .../metrics/CatchAllExceptionMapper.java | 51 ------------------- .../microprofile/metrics/HelloWorldTest.java | 1 + .../server}/CatchAllExceptionMapper.java | 13 ++++- .../metrics/tck/CatchAllExceptionMapper.java | 51 ------------------- .../metrics/tck/MetricsTckCdiExtension.java | 2 + 8 files changed, 17 insertions(+), 157 deletions(-) delete mode 100644 microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java delete mode 100644 microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java rename {integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi => microprofile/server/src/main/java/io/helidon/microprofile/server}/CatchAllExceptionMapper.java (85%) delete mode 100644 microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java diff --git a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java index 8419f5ff7c0..8bb6a8753eb 100644 --- a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java +++ b/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/HelloWorldTest.java @@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.IntStream; +import io.helidon.microprofile.server.CatchAllExceptionMapper; import io.helidon.microprofile.testing.junit5.AddBean; import io.helidon.microprofile.testing.junit5.HelidonTest; diff --git a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java index 497f8fa59e1..fe31cc26999 100644 --- a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java +++ b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/LoadBalancedCoordinatorTest.java @@ -33,7 +33,6 @@ import io.helidon.lra.coordinator.client.CoordinatorClient; import io.helidon.lra.coordinator.client.PropagatedHeaders; import io.helidon.microprofile.config.ConfigCdiExtension; -import io.helidon.microprofile.lra.resources.CatchAllExceptionMapper; import io.helidon.microprofile.lra.resources.CdiNestedCompleteOrCompensate; import io.helidon.microprofile.lra.resources.CommonAfter; import io.helidon.microprofile.lra.resources.DontEnd; @@ -47,6 +46,7 @@ import io.helidon.microprofile.lra.resources.StartAndAfter; import io.helidon.microprofile.lra.resources.Timeout; import io.helidon.microprofile.lra.resources.Work; +import io.helidon.microprofile.server.CatchAllExceptionMapper; import io.helidon.microprofile.server.JaxRsCdiExtension; import io.helidon.microprofile.server.ServerCdiExtension; import io.helidon.microprofile.testing.junit5.AddBean; @@ -95,7 +95,7 @@ @AddExtension(CdiComponentProvider.class) // LRA client @AddExtension(LraCdiExtension.class) -// Test resources +// resources @AddBean(CatchAllExceptionMapper.class) @AddBean(JaxRsCompleteOrCompensate.class) @AddBean(NonJaxRsCompleteOrCompensate.class) diff --git a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java b/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java deleted file mode 100644 index cf01f4a938d..00000000000 --- a/microprofile/lra/jax-rs/src/test/java/io/helidon/microprofile/lra/resources/CatchAllExceptionMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.helidon.microprofile.lra.resources; - -import java.lang.System.Logger.Level; - -import io.helidon.webserver.http.ServerRequest; - -import jakarta.annotation.Priority; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.ext.ExceptionMapper; -import jakarta.ws.rs.ext.Provider; - -/** - * Default mapper for exceptions that are not caught. - */ -@Provider -@Priority(5000) -public class CatchAllExceptionMapper implements ExceptionMapper { - - private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); - @Context - private ServerRequest serverRequest; - - @Override - public Response toResponse(Exception exception) { - serverRequest.context().register("unmappedException", exception); - if (exception instanceof WebApplicationException wae) { - return wae.getResponse(); - } else { - LOGGER.log(Level.WARNING, () -> "Internal server error", exception); - return Response.serverError().build(); - } - } -} diff --git a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java deleted file mode 100644 index ac754f70285..00000000000 --- a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/CatchAllExceptionMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.helidon.microprofile.metrics; - -import java.lang.System.Logger.Level; - -import io.helidon.webserver.http.ServerRequest; - -import jakarta.annotation.Priority; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.ext.ExceptionMapper; -import jakarta.ws.rs.ext.Provider; - -/** - * Default mapper for exceptions that are not caught. - */ -@Provider -@Priority(5000) -public class CatchAllExceptionMapper implements ExceptionMapper { - - private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); - @Context - private ServerRequest serverRequest; - - @Override - public Response toResponse(Exception exception) { - serverRequest.context().register("unmappedException", exception); - if (exception instanceof WebApplicationException wae) { - return wae.getResponse(); - } else { - LOGGER.log(Level.WARNING, () -> "Internal server error", exception); - return Response.serverError().build(); - } - } -} diff --git a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java index 043dff46b04..dc346892d0d 100644 --- a/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java +++ b/microprofile/metrics/src/test/java/io/helidon/microprofile/metrics/HelloWorldTest.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; import java.util.stream.IntStream; +import io.helidon.microprofile.server.CatchAllExceptionMapper; import io.helidon.microprofile.testing.junit5.AddBean; import io.helidon.microprofile.testing.junit5.AddConfig; import io.helidon.microprofile.testing.junit5.HelidonTest; diff --git a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java b/microprofile/server/src/main/java/io/helidon/microprofile/server/CatchAllExceptionMapper.java similarity index 85% rename from integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java rename to microprofile/server/src/main/java/io/helidon/microprofile/server/CatchAllExceptionMapper.java index 8b38fdb090d..43ff30379ed 100644 --- a/integrations/micrometer/cdi/src/test/java/io/helidon/integrations/micrometer/cdi/CatchAllExceptionMapper.java +++ b/microprofile/server/src/main/java/io/helidon/microprofile/server/CatchAllExceptionMapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.helidon.integrations.micrometer.cdi; +package io.helidon.microprofile.server; import java.lang.System.Logger.Level; @@ -28,16 +28,25 @@ import jakarta.ws.rs.ext.Provider; /** - * Default mapper for exceptions that are not caught. + * Mapper for exceptions that are not caught. + * + * It is not configured by default in Helidon but it is provided for explicit usage. */ @Provider @Priority(5000) public class CatchAllExceptionMapper implements ExceptionMapper { private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); + @Context private ServerRequest serverRequest; + /** + * Default empty constructor. + */ + public CatchAllExceptionMapper() { + } + @Override public Response toResponse(Exception exception) { serverRequest.context().register("unmappedException", exception); diff --git a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java deleted file mode 100644 index 8b98053f2ca..00000000000 --- a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/CatchAllExceptionMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Oracle and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.helidon.microprofile.metrics.tck; - -import java.lang.System.Logger.Level; - -import io.helidon.webserver.http.ServerRequest; - -import jakarta.annotation.Priority; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.ext.ExceptionMapper; -import jakarta.ws.rs.ext.Provider; - -/** - * Default mapper for exceptions that are not caught. - */ -@Provider -@Priority(5000) -public class CatchAllExceptionMapper implements ExceptionMapper { - - private static final System.Logger LOGGER = System.getLogger(CatchAllExceptionMapper.class.getName()); - @Context - private ServerRequest serverRequest; - - @Override - public Response toResponse(Exception exception) { - serverRequest.context().register("unmappedException", exception); - if (exception instanceof WebApplicationException wae) { - return wae.getResponse(); - } else { - LOGGER.log(Level.WARNING, () -> "Internal server error", exception); - return Response.serverError().build(); - } - } -} diff --git a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java index 9cce6ae7083..381c02b800c 100644 --- a/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java +++ b/microprofile/tests/tck/tck-metrics/src/test/java/io/helidon/microprofile/metrics/tck/MetricsTckCdiExtension.java @@ -15,6 +15,8 @@ */ package io.helidon.microprofile.metrics.tck; +import io.helidon.microprofile.server.CatchAllExceptionMapper; + import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; import jakarta.enterprise.inject.spi.Extension;