Skip to content

Commit

Permalink
CXF-9039: Run Jakarta RESTful Web Services 3.1 TCK. Fix SeBootstrap t…
Browse files Browse the repository at this point in the history
…est cases (#2186)
  • Loading branch information
reta authored Dec 12, 2024
1 parent 5dbbe39 commit 483fe3b
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,20 @@ public <T> SeBootstrap.Configuration.Builder from(BiFunction<String, Class<T>, O
return this;
}

@Override
public SeBootstrap.Configuration.Builder from(Object externalConfig) {
if (SeBootstrap.Configuration.class.isInstance(externalConfig)) {
final SeBootstrap.Configuration other = (SeBootstrap.Configuration) externalConfig;
from((name, clazz) -> {
final Object property = other.property(name);
if (property != null && clazz.equals(property.getClass())) {
return Optional.of(property);
} else {
return Optional.empty();
}
});
}
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@

package org.apache.cxf.jaxrs.impl;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.Date;
import java.util.HashMap;
Expand Down Expand Up @@ -55,6 +58,8 @@
import org.apache.cxf.jaxrs.utils.ResourceUtils;

public class RuntimeDelegateImpl extends RuntimeDelegate {
// The default value is implementation specific, using non-priviledged default port
private static final int DEFAULT_HTTP_PORT = 8080;
protected Map<Class<?>, HeaderDelegate<?>> headerProviders = new HashMap<>();

public RuntimeDelegateImpl() {
Expand Down Expand Up @@ -144,7 +149,30 @@ public Builder createConfigurationBuilder() {
@Override
public CompletionStage<Instance> bootstrap(Application application, Configuration configuration) {
final JAXRSServerFactoryBean factory = ResourceUtils.createApplication(application, false, false, false, null);
final URI address = configuration.baseUriBuilder().path(factory.getAddress()).build();

Configuration.Builder instanceConfigurationBuilder = Configuration.builder().from(configuration);
if (!configuration.hasProperty(Configuration.HOST)) { // The default value is "localhost"
instanceConfigurationBuilder = instanceConfigurationBuilder.host("localhost");
}

if (!configuration.hasProperty(Configuration.PROTOCOL)) { // The default value is "HTTP"
instanceConfigurationBuilder = instanceConfigurationBuilder.protocol("HTTP");
}

if (!configuration.hasProperty(Configuration.PORT)) {
instanceConfigurationBuilder = instanceConfigurationBuilder.port(DEFAULT_HTTP_PORT);
} else if (configuration.port() == Configuration.FREE_PORT) {
instanceConfigurationBuilder = instanceConfigurationBuilder.port(findFreePort()); /* free port */
} else if (configuration.port() == Configuration.DEFAULT_PORT) {
instanceConfigurationBuilder = instanceConfigurationBuilder.port(DEFAULT_HTTP_PORT);
}

if (!configuration.hasProperty(Configuration.ROOT_PATH)) { // The default value is "/"
instanceConfigurationBuilder = instanceConfigurationBuilder.rootPath("/");
}

final Configuration instanceConfiguration = instanceConfigurationBuilder.build();
final URI address = instanceConfiguration.baseUriBuilder().path(factory.getAddress()).build();
factory.setAddress(address.toString());
factory.setStart(true);

Expand Down Expand Up @@ -174,9 +202,10 @@ public CompletionStage<Instance> bootstrap(Application application, Configuratio

return CompletableFuture
.supplyAsync(() -> factory.create())
.thenApply(s -> new InstanceImpl(s, configuration));
.thenApply(s -> new InstanceImpl(s, instanceConfiguration));
}

@SuppressWarnings({ "removal", "deprecation" })
@Override
public CompletionStage<Instance> bootstrap(Class<? extends Application> clazz, Configuration configuration) {
try {
Expand All @@ -198,4 +227,15 @@ public Application run() throws Exception {
public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException {
return new EntityPartBuilderImpl(partName);
}

@SuppressWarnings({ "removal", "deprecation" })
private static int findFreePort() {
return AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
} catch (final IOException e) {
return -1;
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ public UriBuilder port(int thePort) throws IllegalArgumentException {

@Override
public UriBuilder scheme(String s) throws IllegalArgumentException {
scheme = s;
scheme = (s != null) ? s.toLowerCase() : s;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.cxf.systest.jaxrs.bootstrap;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.CompletionStage;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.SeBootstrap;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.UriBuilder;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;

/**
* Some tests are taken from {@linkplain https://github.com/jakartaee/rest/blob/tck-3.1.2/jaxrs-tck
* /src/main/java/ee/jakarta/tck/ws/rs/sebootstrap/SeBootstrapIT.java}
*/
public class SeBootstrapTest {
private Client client;

@Before
public void setUp() {
client = ClientBuilder.newClient();
}

@After
public void tearDown() {
client.close();
}

/**
* Verifies that an instance will boot using default configuration.
*/
@Test
public final void shouldBootInstanceUsingDefaults() {
final Application application = new StaticApplication();
final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.build();

final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application,
requestedConfiguration);
final SeBootstrap.Instance instance = completionStage.toCompletableFuture().join();
final SeBootstrap.Configuration actualConfiguration = instance.configuration();
final String actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
.host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
.path("application/resource")).request().get(String.class);

assertThat(actualResponse, is("OK"));
assertThat(actualConfiguration.protocol(), is("HTTP"));
assertThat(actualConfiguration.host(), is("localhost"));
assertThat(actualConfiguration.port(), is(greaterThan(0)));
assertThat(actualConfiguration.rootPath(), is("/"));

instance.stop().toCompletableFuture().join();
}

/**
* Verifies that an instance will boot using a self-detected free IP port.
*/
@Test
public final void shouldBootInstanceUsingSelfDetectedFreeIpPort() {
final Application application = new StaticApplication();
final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP")
.host("localhost").port(SeBootstrap.Configuration.FREE_PORT).rootPath("/root/path").build();

final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application,
requestedConfiguration);
final SeBootstrap.Instance instance = completionStage.toCompletableFuture().join();
final SeBootstrap.Configuration actualConfiguration = instance.configuration();
final String actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
.host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
.path("application/resource")).request().get(String.class);

assertThat(actualResponse, is("OK"));
assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
assertThat(actualConfiguration.port(), is(greaterThan(0)));
assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
instance.stop().toCompletableFuture().join();
}

@Test
public final void shouldBootInstanceUsingImplementationsDefaultIpPort() {
final Application application = new StaticApplication();
final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder();
final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.protocol("HTTP")
.host("localhost").port(SeBootstrap.Configuration.DEFAULT_PORT).rootPath("/root/path").build();

final CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application,
requestedConfiguration);
final SeBootstrap.Instance instance = completionStage.toCompletableFuture().join();
final SeBootstrap.Configuration actualConfiguration = instance.configuration();
final String actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol())
.host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath())
.path("application/resource")).request().get(String.class);

assertThat(actualResponse, is("OK"));
assertThat(actualConfiguration.protocol(), is(requestedConfiguration.protocol()));
assertThat(actualConfiguration.host(), is(requestedConfiguration.host()));
assertThat(actualConfiguration.port(), is(greaterThan(0)));
assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath()));
instance.stop().toCompletableFuture().join();
}

@ApplicationPath("application")
public static final class StaticApplication extends Application {
private final StaticResource staticResource;

private StaticApplication() {
this.staticResource = new StaticResource();
}

@Override
public Set<Object> getSingletons() {
return Collections.<Object>singleton(staticResource);
}

@Path("resource")
public static final class StaticResource {
private StaticResource() {
}

@GET
public String staticResponse() {
return "OK";
}
}
};
}
2 changes: 1 addition & 1 deletion tck/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pipeline {
stage('Download JakartaEE Restful Services TCK') {
steps {
checkout([$class: 'GitSCM',
branches: [[name: 'refs/tags/3.1.0']],
branches: [[name: 'refs/tags/tck-3.1.2']],
userRemoteConfigs: [[url: 'https://github.com/jakartaee/rest/']],
extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'rest']]
])
Expand Down
19 changes: 18 additions & 1 deletion tck/cxf-tck/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<cxf.version>4.1.0-SNAPSHOT</cxf.version>
<cxf.version>4.1.1-SNAPSHOT</cxf.version>
<glassfish.container.version>7.0.16</glassfish.container.version>
<glassfish.home>${project.build.directory}/glassfish7</glassfish.home>
<jakarta.platform.version>10.0.0</jakarta.platform.version>
Expand Down Expand Up @@ -155,6 +155,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
Expand Down Expand Up @@ -582,5 +588,16 @@
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>apache-snapshots</id>
<name>Apache SNAPSHOT Repository</name>
<url>https://repository.apache.org/content/groups/snapshots-group/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
</project>

0 comments on commit 483fe3b

Please sign in to comment.