Skip to content

Commit

Permalink
issue-42851: port resteasy fix for sub-resources from resteasy/restea…
Browse files Browse the repository at this point in the history
…sy-microprofile PR quarkusio#241
  • Loading branch information
maxr2011-tech11 committed Sep 2, 2024
1 parent dcd9928 commit 9df0827
Show file tree
Hide file tree
Showing 8 changed files with 439 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package io.quarkus.restclient.exception;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;

import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.restclient.exception.resource.ClientRootResource;
import io.quarkus.restclient.exception.resource.ClientSubResource;
import io.quarkus.restclient.exception.resource.ServerResource;
import io.quarkus.restclient.exception.resource.TestException;
import io.quarkus.restclient.exception.resource.TestExceptionMapper;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

/**
* Tests client sub-resources
*
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class SubResourceTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(SubResourceTest.class,
ClientRootResource.class, ClientSubResource.class, ServerResource.class,
TestExceptionMapper.class, TestException.class));

@TestHTTPResource
URL url;

/**
* Creates a REST client with an attached exception mapper. The exception mapper will throw a {@link TestException}.
* This test invokes a call to the root resource.
*
* @throws Exception if a test error occurs
*/
@Test
public void rootResourceExceptionMapper() {
try (final ClientRootResource rootResource = RestClientBuilder.newBuilder().baseUrl(url)
.build(ClientRootResource.class)) {
rootResource.fromRoot();
fail("fromRoot() should have thrown a TestException");
} catch (TestException expected) {
assertEquals("RootResource failed on purpose", expected.getMessage());
} catch (Exception e) {
failWithException(e, "fromRoot");
}
}

/**
* Creates a REST client with an attached exception mapper. The exception mapper will throw a {@link TestException}.
* This test invokes a call to the sub-resource. The sub-resource then invokes an additional call which should also
* result in a {@link TestException} thrown.
*
* @throws Exception if a test error occurs
*/
@Test
public void subResourceExceptionMapper() {
try (final ClientRootResource rootResource = RestClientBuilder.newBuilder().baseUrl(url)
.build(ClientRootResource.class)) {
final ClientSubResource subResource = rootResource.subResource();
assertNotNull(subResource, "The SubResource should not be null");
subResource.fromSub();
fail("fromSub() should have thrown a TestException");
} catch (TestException expected) {
assertEquals("SubResource failed on purpose", expected.getMessage());
} catch (Exception e) {
failWithException(e, "fromSub");
}
}

/**
* This test invokes a call to the sub-resource. The sub-resource then invokes an additional call which should
* return the header value for {@code test-header}.
*
* @throws Exception if a test error occurs
*/
@Test
public void subResourceWithHeader() throws Exception {
try (final ClientRootResource rootResource = RestClientBuilder.newBuilder().baseUrl(url)
.build(ClientRootResource.class)) {
final ClientSubResource subResource = rootResource.subResource();
assertNotNull(subResource, "The SubResource should not be null");
try (final Response response = subResource.withHeader()) {
assertEquals(Response.Status.OK, response.getStatusInfo());
assertEquals("SubResourceHeader", response.readEntity(String.class));
}
}
}

/**
* This test invokes a call to the sub-resource. The sub-resource then invokes an additional call which should
* return the header value for {@code test-global-header}.
*
* @throws Exception if a test error occurs
*/
@Test
public void subResourceWithGlobalHeader() throws Exception {
try (final ClientRootResource rootResource = RestClientBuilder.newBuilder().baseUrl(url)
.build(ClientRootResource.class)) {
final ClientSubResource subResource = rootResource.subResource();
assertNotNull(subResource, "The SubResource should not be null");
try (final Response response = subResource.withGlobalHeader()) {
assertEquals(Response.Status.OK, response.getStatusInfo());
assertEquals("GlobalSubResourceHeader", response.readEntity(String.class));
}
}
}

private static void failWithException(final Exception e, final String methodName) {
final StringWriter writer = new StringWriter();
writer.write(methodName);
writer.write("() should have thrown an TestException. Instead got: ");
writer.write(System.lineSeparator());
e.printStackTrace(new PrintWriter(writer));
fail(writer.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.quarkus.restclient.exception.resource;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
@RegisterRestClient
@Path("/root")
public interface ClientRootResource extends AutoCloseable {

@Path("/sub")
ClientSubResource subResource();

@GET
Response fromRoot() throws TestException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.quarkus.restclient.exception.resource;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
@ClientHeaderParam(name = "test-global-header", value = "GlobalSubResourceHeader")
public interface ClientSubResource {

@GET
Response fromSub() throws TestException;

@GET
@ClientHeaderParam(name = "test-header", value = "SubResourceHeader")
@Path("/header")
@Produces(MediaType.TEXT_PLAIN)
Response withHeader();

@GET
@Path("/global/header")
@Produces(MediaType.TEXT_PLAIN)
Response withGlobalHeader();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.quarkus.restclient.exception.resource;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
@Path("/root")
public class ServerResource {

@GET
public Response fromRoot() {
return Response.serverError().entity("RootResource failed on purpose").build();
}

@GET
@Path("/sub")
public Response fromSub() {
return Response.serverError().entity("SubResource failed on purpose").build();
}

@GET
@Path("/sub/header")
@Produces(MediaType.TEXT_PLAIN)
public Response subHeader(@HeaderParam("test-header") final String value) {
return Response.ok(value).build();
}

@GET
@Path("/sub/global/header")
@Produces(MediaType.TEXT_PLAIN)
public Response subGlobalHeader(@HeaderParam("test-global-header") final String value) {
return Response.ok(value).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.quarkus.restclient.exception.resource;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
public class TestException extends RuntimeException {

public TestException(final String msg) {
super(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2024 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.quarkus.restclient.exception.resource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;

/**
* @author <a href="mailto:[email protected]">James R. Perkins</a>
*/
@ApplicationScoped
public class TestExceptionMapper implements ResponseExceptionMapper<TestException> {
@Override
public TestException toThrowable(final Response response) {
return new TestException(response.readEntity(String.class));
}
}
Loading

0 comments on commit 9df0827

Please sign in to comment.